PluginProbe ʕ •ᴥ•ʔ
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI / 3.5.3
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI v3.5.3
3.5.3 3.5.2 3.5.1 3.5.0 3.4.8 3.4.7 3.4.6 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.5.1 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.10 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.6.1 1.6.7 1.7.0 1.7.0.1 1.7.0.2 1.7.0.3 1.7.1 1.7.2 1.7.2.1 1.7.2.2 1.7.3 1.7.4 1.7.5 1.7.5.1 1.7.5.2 1.7.6 1.7.7 1.7.7.1 1.7.7.2 1.7.8 1.7.9 1.8.0 1.8.0.1 1.8.1 1.8.2 1.8.2.1 1.8.2.2 1.8.2.3 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.0.1 1.9.1 1.9.2 1.9.3 1.9.4 1.9.4.1 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.0.1 2.0.1 2.0.2 2.0.3 2.0.3.1 2.0.4 2.0.4.1 2.0.5 2.0.6 2.0.7 2.0.8 2.0.8.1 2.0.9 3.0.0 3.0.0.1 3.0.1 3.0.2 3.0.3 3.0.3.1 3.0.4 3.0.4.1 3.0.4.2 3.0.5 3.0.5.1 3.0.5.2 3.0.6 3.0.6.1 3.0.7.1 3.0.8 3.0.8.1 3.0.9 3.0.9.1 3.0.9.2 3.0.9.3 3.0.9.4 3.0.9.5 3.1.0 3.1.1 3.1.2 3.2.0 3.2.1 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.3.0 3.4.0 3.4.1 3.4.2 3.4.2.1 3.4.3 3.4.4 3.4.5 trunk 1.0 1.0.1 1.0.2 1.0.3
everest-forms / assets / js / intlTelInput / jquery.intlTelInput.js
everest-forms / assets / js / intlTelInput Last commit date
jquery.intlTelInput.js 2 years ago jquery.intlTelInput.min.js 2 years ago utils.js 2 years ago
jquery.intlTelInput.js
1375 lines
1 /*
2 * International Telephone Input v17.0.0
3 * https://github.com/jackocnr/intl-tel-input.git
4 * Licensed under the MIT license
5 */
6
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($);
14 });
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" ], [ "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", "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, [ "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 ], [ "Cocos (Keeling) Islands", "cc", "61", 1 ], [ "Colombia", "co", "57" ], [ "Comoros (‫جزر الق�
33 ر‬‎)", "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 (‫�
34 صر‬‎)", "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", "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 (Каза�
35 стан)", "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" ], [ "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 (‫�
36 وريتانيا‬‎)", "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 (‫ال�
37 غرب‬‎)", "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", "1", 17, [ "670" ] ], [ "Norway (Norge)", "no", "47", 0 ], [ "Oman (‫عُ�
38 ان‬‎)", "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 (‫ال�
39
40 لكة العربية السعودية‬‎)", "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" ] ], [ "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", "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 (‫الإ�
41 ارات العربية ال�
42 تحدة‬‎)", "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 (‫الي�
43 ن‬‎)", "ye", "967" ], [ "Zambia", "zm", "260" ], [ "Zimbabwe", "zw", "263" ], [ "�
44 land Islands", "ax", "358", 1, [ "18" ] ] ];
45 // loop over all of the countries above, restructuring the data to be objects with named keys
46 for (var i = 0; i < allCountries.length; i++) {
47 var c = allCountries[i];
48 allCountries[i] = {
49 name: c[0],
50 iso2: c[1],
51 dialCode: c[2],
52 priority: c[3] || 0,
53 areaCodes: c[4] || null
54 };
55 }
56 "use strict";
57 function _classCallCheck(instance, Constructor) {
58 if (!(instance instanceof Constructor)) {
59 throw new TypeError("Cannot call a class as a function");
60 }
61 }
62 function _defineProperties(target, props) {
63 for (var i = 0; i < props.length; i++) {
64 var descriptor = props[i];
65 descriptor.enumerable = descriptor.enumerable || false;
66 descriptor.configurable = true;
67 if ("value" in descriptor) descriptor.writable = true;
68 Object.defineProperty(target, descriptor.key, descriptor);
69 }
70 }
71 function _createClass(Constructor, protoProps, staticProps) {
72 if (protoProps) _defineProperties(Constructor.prototype, protoProps);
73 if (staticProps) _defineProperties(Constructor, staticProps);
74 return Constructor;
75 }
76 var intlTelInputGlobals = {
77 getInstance: function getInstance(input) {
78 var id = input.getAttribute("data-intl-tel-input-id");
79 return window.intlTelInputGlobals.instances[id];
80 },
81 instances: {}
82 };
83 if (typeof window === "object") window.intlTelInputGlobals = intlTelInputGlobals;
84 // these vars persist through all instances of the plugin
85 var id = 0;
86 var defaults = {
87 // whether or not to allow the dropdown
88 allowDropdown: true,
89 // if there is just a dial code in the input: remove it on blur
90 autoHideDialCode: true,
91 // add a placeholder in the input with an example number for the selected country
92 autoPlaceholder: "polite",
93 // modify the parentClass
94 customContainer: "",
95 // modify the auto placeholder
96 customPlaceholder: null,
97 // append menu to specified element
98 dropdownContainer: null,
99 // don't display these countries
100 excludeCountries: [],
101 // format the input value during initialisation and on setNumber
102 formatOnDisplay: true,
103 // geoIp lookup function
104 geoIpLookup: null,
105 // inject a hidden input with this name, and on submit, populate it with the result of getNumber
106 hiddenInput: "",
107 // initial country
108 initialCountry: "",
109 // localized country names e.g. { 'de': 'Deutschland' }
110 localizedCountries: null,
111 // don't insert international dial codes
112 nationalMode: true,
113 // display only these countries
114 onlyCountries: [],
115 // number type to use for placeholders
116 placeholderNumberType: "MOBILE",
117 // the countries at the top of the list. defaults to united states and united kingdom
118 preferredCountries: [ "us", "gb" ],
119 // display the country dial code next to the selected flag so it's not part of the typed number
120 separateDialCode: false,
121 // specify the path to the libphonenumber script to enable validation/formatting
122 utilsScript: ""
123 };
124 // https://en.wikipedia.org/wiki/List_of_North_American_Numbering_Plan_area_codes#Non-geographic_area_codes
125 var regionlessNanpNumbers = [ "800", "822", "833", "844", "855", "866", "877", "880", "881", "882", "883", "884", "885", "886", "887", "888", "889" ];
126 if (typeof window === "object") {
127 // keep track of if the window.load event has fired as impossible to check after the fact
128 window.addEventListener("load", function() {
129 // UPDATE: use a public static field so we can fudge it in the tests
130 window.intlTelInputGlobals.windowLoaded = true;
131 });
132 }
133 // utility function to iterate over an object. can't use Object.entries or native forEach because
134 // of IE11
135 var forEachProp = function forEachProp(obj, callback) {
136 var keys = Object.keys(obj);
137 for (var i = 0; i < keys.length; i++) {
138 callback(keys[i], obj[keys[i]]);
139 }
140 };
141 // run a method on each instance of the plugin
142 var forEachInstance = function forEachInstance(method) {
143 forEachProp(window.intlTelInputGlobals.instances, function(key) {
144 window.intlTelInputGlobals.instances[key][method]();
145 });
146 };
147 // this is our plugin class that we will create an instance of
148 // eslint-disable-next-line no-unused-vars
149 var Iti = /*#__PURE__*/
150 function() {
151 function Iti(input, options) {
152 var _this = this;
153 _classCallCheck(this, Iti);
154 this.id = id++;
155 this.telInput = input;
156 this.activeItem = null;
157 this.highlightedItem = null;
158 // process specified options / defaults
159 // alternative to Object.assign, which isn't supported by IE11
160 var customOptions = options || {};
161 this.options = {};
162 forEachProp(defaults, function(key, value) {
163 _this.options[key] = customOptions.hasOwnProperty(key) ? customOptions[key] : value;
164 });
165 this.hadInitialPlaceholder = Boolean(input.getAttribute("placeholder"));
166 }
167 _createClass(Iti, [ {
168 key: "_init",
169 value: function _init() {
170 var _this2 = this;
171 // if in nationalMode, disable options relating to dial codes
172 if (this.options.nationalMode) this.options.autoHideDialCode = false;
173 // if separateDialCode then doesn't make sense to A) insert dial code into input
174 // (autoHideDialCode), and B) display national numbers (because we're displaying the country
175 // dial code next to them)
176 if (this.options.separateDialCode) {
177 this.options.autoHideDialCode = this.options.nationalMode = false;
178 }
179 // we cannot just test screen size as some smartphones/website meta tags will report desktop
180 // resolutions
181 // Note: for some reason jasmine breaks if you put this in the main Plugin function with the
182 // rest of these declarations
183 // Note: to target Android Mobiles (and not Tablets), we must find 'Android' and 'Mobile'
184 this.isMobile = /Android.+Mobile|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
185 if (this.isMobile) {
186 // trigger the mobile dropdown css
187 document.body.classList.add("iti-mobile");
188 // on mobile, we want a full screen dropdown, so we must append it to the body
189 if (!this.options.dropdownContainer) this.options.dropdownContainer = document.body;
190 }
191 // these promises get resolved when their individual requests complete
192 // this way the dev can do something like iti.promise.then(...) to know when all requests are
193 // complete
194 if (typeof Promise !== "undefined") {
195 var autoCountryPromise = new Promise(function(resolve, reject) {
196 _this2.resolveAutoCountryPromise = resolve;
197 _this2.rejectAutoCountryPromise = reject;
198 });
199 var utilsScriptPromise = new Promise(function(resolve, reject) {
200 _this2.resolveUtilsScriptPromise = resolve;
201 _this2.rejectUtilsScriptPromise = reject;
202 });
203 this.promise = Promise.all([ autoCountryPromise, utilsScriptPromise ]);
204 } else {
205 // prevent errors when Promise doesn't exist
206 this.resolveAutoCountryPromise = this.rejectAutoCountryPromise = function() {};
207 this.resolveUtilsScriptPromise = this.rejectUtilsScriptPromise = function() {};
208 }
209 // in various situations there could be no country selected initially, but we need to be able
210 // to assume this variable exists
211 this.selectedCountryData = {};
212 // process all the data: onlyCountries, excludeCountries, preferredCountries etc
213 this._processCountryData();
214 // generate the markup
215 this._generateMarkup();
216 // set the initial state of the input value and the selected flag
217 this._setInitialState();
218 // start all of the event listeners: autoHideDialCode, input keydown, selectedFlag click
219 this._initListeners();
220 // utils script, and auto country
221 this._initRequests();
222 }
223 }, {
224 key: "_processCountryData",
225 value: function _processCountryData() {
226 // process onlyCountries or excludeCountries array if present
227 this._processAllCountries();
228 // process the countryCodes map
229 this._processCountryCodes();
230 // process the preferredCountries
231 this._processPreferredCountries();
232 // translate countries according to localizedCountries option
233 if (this.options.localizedCountries) this._translateCountriesByLocale();
234 // sort countries by name
235 if (this.options.onlyCountries.length || this.options.localizedCountries) {
236 this.countries.sort(this._countryNameSort);
237 }
238 }
239 }, {
240 key: "_addCountryCode",
241 value: function _addCountryCode(iso2, dialCode, priority) {
242 if (dialCode.length > this.dialCodeMaxLen) {
243 this.dialCodeMaxLen = dialCode.length;
244 }
245 if (!this.countryCodes.hasOwnProperty(dialCode)) {
246 this.countryCodes[dialCode] = [];
247 }
248 // bail if we already have this country for this dialCode
249 for (var i = 0; i < this.countryCodes[dialCode].length; i++) {
250 if (this.countryCodes[dialCode][i] === iso2) return;
251 }
252 // check for undefined as 0 is falsy
253 var index = priority !== undefined ? priority : this.countryCodes[dialCode].length;
254 this.countryCodes[dialCode][index] = iso2;
255 }
256 }, {
257 key: "_processAllCountries",
258 value: function _processAllCountries() {
259 if (this.options.onlyCountries.length) {
260 var lowerCaseOnlyCountries = this.options.onlyCountries.map(function(country) {
261 return country.toLowerCase();
262 });
263 this.countries = allCountries.filter(function(country) {
264 return lowerCaseOnlyCountries.indexOf(country.iso2) > -1;
265 });
266 } else if (this.options.excludeCountries.length) {
267 var lowerCaseExcludeCountries = this.options.excludeCountries.map(function(country) {
268 return country.toLowerCase();
269 });
270 this.countries = allCountries.filter(function(country) {
271 return lowerCaseExcludeCountries.indexOf(country.iso2) === -1;
272 });
273 } else {
274 this.countries = allCountries;
275 }
276 }
277 }, {
278 key: "_translateCountriesByLocale",
279 value: function _translateCountriesByLocale() {
280 for (var i = 0; i < this.countries.length; i++) {
281 var iso = this.countries[i].iso2.toLowerCase();
282 if (this.options.localizedCountries.hasOwnProperty(iso)) {
283 this.countries[i].name = this.options.localizedCountries[iso];
284 }
285 }
286 }
287 }, {
288 key: "_countryNameSort",
289 value: function _countryNameSort(a, b) {
290 return a.name.localeCompare(b.name);
291 }
292 }, {
293 key: "_processCountryCodes",
294 value: function _processCountryCodes() {
295 this.dialCodeMaxLen = 0;
296 this.countryCodes = {};
297 // first: add dial codes
298 for (var i = 0; i < this.countries.length; i++) {
299 var c = this.countries[i];
300 this._addCountryCode(c.iso2, c.dialCode, c.priority);
301 }
302 // next: add area codes
303 // this is a second loop over countries, to make sure we have all of the "root" countries
304 // already in the map, so that we can access them, as each time we add an area code substring
305 // to the map, we also need to include the "root" country's code, as that also matches
306 for (var _i = 0; _i < this.countries.length; _i++) {
307 var _c = this.countries[_i];
308 // area codes
309 if (_c.areaCodes) {
310 var rootCountryCode = this.countryCodes[_c.dialCode][0];
311 // for each area code
312 for (var j = 0; j < _c.areaCodes.length; j++) {
313 var areaCode = _c.areaCodes[j];
314 // for each digit in the area code to add all partial matches as well
315 for (var k = 1; k < areaCode.length; k++) {
316 var partialDialCode = _c.dialCode + areaCode.substr(0, k);
317 // start with the root country, as that also matches this dial code
318 this._addCountryCode(rootCountryCode, partialDialCode);
319 this._addCountryCode(_c.iso2, partialDialCode);
320 }
321 // add the full area code
322 this._addCountryCode(_c.iso2, _c.dialCode + areaCode);
323 }
324 }
325 }
326 }
327 }, {
328 key: "_processPreferredCountries",
329 value: function _processPreferredCountries() {
330 this.preferredCountries = [];
331 for (var i = 0; i < this.options.preferredCountries.length; i++) {
332 var countryCode = this.options.preferredCountries[i].toLowerCase();
333 var countryData = this._getCountryData(countryCode, false, true);
334 if (countryData) this.preferredCountries.push(countryData);
335 }
336 }
337 }, {
338 key: "_createEl",
339 value: function _createEl(name, attrs, container) {
340 var el = document.createElement(name);
341 if (attrs) forEachProp(attrs, function(key, value) {
342 return el.setAttribute(key, value);
343 });
344 if (container) container.appendChild(el);
345 return el;
346 }
347 }, {
348 key: "_generateMarkup",
349 value: function _generateMarkup() {
350 // if autocomplete does not exist on the element and its form, then
351 // prevent autocomplete as there's no safe, cross-browser event we can react to, so it can
352 // easily put the plugin in an inconsistent state e.g. the wrong flag selected for the
353 // autocompleted number, which on submit could mean wrong number is saved (esp in nationalMode)
354 if (!this.telInput.hasAttribute("autocomplete") && !(this.telInput.form && this.telInput.form.hasAttribute("autocomplete"))) {
355 this.telInput.setAttribute("autocomplete", "off");
356 }
357 // containers (mostly for positioning)
358 var parentClass = "iti";
359 if (this.options.allowDropdown) parentClass += " iti--allow-dropdown";
360 if (this.options.separateDialCode) parentClass += " iti--separate-dial-code";
361 if (this.options.customContainer) {
362 parentClass += " ";
363 parentClass += this.options.customContainer;
364 }
365 var wrapper = this._createEl("div", {
366 "class": parentClass
367 });
368 this.telInput.parentNode.insertBefore(wrapper, this.telInput);
369 this.flagsContainer = this._createEl("div", {
370 "class": "iti__flag-container"
371 }, wrapper);
372 wrapper.appendChild(this.telInput);
373 // selected flag (displayed to left of input)
374 this.selectedFlag = this._createEl("div", {
375 "class": "iti__selected-flag",
376 role: "combobox",
377 "aria-owns": "iti-".concat(this.id, "__country-listbox"),
378 "aria-expanded": "false"
379 }, this.flagsContainer);
380 this.selectedFlagInner = this._createEl("div", {
381 "class": "iti__flag"
382 }, this.selectedFlag);
383 if (this.options.separateDialCode) {
384 this.selectedDialCode = this._createEl("div", {
385 "class": "iti__selected-dial-code"
386 }, this.selectedFlag);
387 }
388 if (this.options.allowDropdown) {
389 // make element focusable and tab navigable
390 this.selectedFlag.setAttribute("tabindex", "0");
391 this.dropdownArrow = this._createEl("div", {
392 "class": "iti__arrow"
393 }, this.selectedFlag);
394 // country dropdown: preferred countries, then divider, then all countries
395 this.countryList = this._createEl("ul", {
396 "class": "iti__country-list iti__hide",
397 id: "iti-".concat(this.id, "__country-listbox"),
398 role: "listbox"
399 });
400 if (this.preferredCountries.length) {
401 this._appendListItems(this.preferredCountries, "iti__preferred", true);
402 this._createEl("li", {
403 "class": "iti__divider",
404 role: "separator",
405 "aria-disabled": "true"
406 }, this.countryList);
407 }
408 this._appendListItems(this.countries, "iti__standard");
409 // create dropdownContainer markup
410 if (this.options.dropdownContainer) {
411 this.dropdown = this._createEl("div", {
412 "class": "iti iti--container"
413 });
414 this.dropdown.appendChild(this.countryList);
415 } else {
416 this.flagsContainer.appendChild(this.countryList);
417 }
418 }
419 if (this.options.hiddenInput) {
420 var hiddenInputName = this.options.hiddenInput;
421 var name = this.telInput.getAttribute("name");
422 if (name) {
423 var i = name.lastIndexOf("[");
424 // if input name contains square brackets, then give the hidden input the same name,
425 // replacing the contents of the last set of brackets with the given hiddenInput name
426 if (i !== -1) hiddenInputName = "".concat(name.substr(0, i), "[").concat(hiddenInputName, "]");
427 }
428 this.hiddenInput = this._createEl("input", {
429 type: "hidden",
430 name: hiddenInputName
431 });
432 wrapper.appendChild(this.hiddenInput);
433 }
434 }
435 }, {
436 key: "_appendListItems",
437 value: function _appendListItems(countries, className, preferred) {
438 // we create so many DOM elements, it is faster to build a temp string
439 // and then add everything to the DOM in one go at the end
440 var tmp = "";
441 // for each country
442 for (var i = 0; i < countries.length; i++) {
443 var c = countries[i];
444 var idSuffix = preferred ? "-preferred" : "";
445 // open the list item
446 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, "'>");
447 // add the flag
448 tmp += "<div class='iti__flag-box'><div class='iti__flag iti__".concat(c.iso2, "'></div></div>");
449 // and the country name and dial code
450 tmp += "<span class='iti__country-name'>".concat(c.name, "</span>");
451 tmp += "<span class='iti__dial-code'>+".concat(c.dialCode, "</span>");
452 // close the list item
453 tmp += "</li>";
454 }
455 this.countryList.insertAdjacentHTML("beforeend", tmp);
456 }
457 }, {
458 key: "_setInitialState",
459 value: function _setInitialState() {
460 var val = this.telInput.value;
461 var dialCode = this._getDialCode(val);
462 var isRegionlessNanp = this._isRegionlessNanp(val);
463 var _this$options = this.options, initialCountry = _this$options.initialCountry, nationalMode = _this$options.nationalMode, autoHideDialCode = _this$options.autoHideDialCode, separateDialCode = _this$options.separateDialCode;
464 // if we already have a dial code, and it's not a regionlessNanp, we can go ahead and set the
465 // flag, else fall back to the default country
466 if (dialCode && !isRegionlessNanp) {
467 this._updateFlagFromNumber(val);
468 } else if (initialCountry !== "auto") {
469 // see if we should select a flag
470 if (initialCountry) {
471 this._setFlag(initialCountry.toLowerCase());
472 } else {
473 if (dialCode && isRegionlessNanp) {
474 // has intl dial code, is regionless nanp, and no initialCountry, so default to US
475 this._setFlag("us");
476 } else {
477 // no dial code and no initialCountry, so default to first in list
478 this.defaultCountry = this.preferredCountries.length ? this.preferredCountries[0].iso2 : this.countries[0].iso2;
479 if (!val) {
480 this._setFlag(this.defaultCountry);
481 }
482 }
483 }
484 // if empty and no nationalMode and no autoHideDialCode then insert the default dial code
485 if (!val && !nationalMode && !autoHideDialCode && !separateDialCode) {
486 this.telInput.value = "+".concat(this.selectedCountryData.dialCode);
487 }
488 }
489 // NOTE: if initialCountry is set to auto, that will be handled separately
490 // format - note this wont be run after _updateDialCode as that's only called if no val
491 if (val) this._updateValFromNumber(val);
492 }
493 }, {
494 key: "_initListeners",
495 value: function _initListeners() {
496 this._initKeyListeners();
497 if (this.options.autoHideDialCode) this._initBlurListeners();
498 if (this.options.allowDropdown) this._initDropdownListeners();
499 if (this.hiddenInput) this._initHiddenInputListener();
500 }
501 }, {
502 key: "_initHiddenInputListener",
503 value: function _initHiddenInputListener() {
504 var _this3 = this;
505 this._handleHiddenInputSubmit = function() {
506 _this3.hiddenInput.value = _this3.getNumber();
507 };
508 if (this.telInput.form) this.telInput.form.addEventListener("submit", this._handleHiddenInputSubmit);
509 }
510 }, {
511 key: "_getClosestLabel",
512 value: function _getClosestLabel() {
513 var el = this.telInput;
514 while (el && el.tagName !== "LABEL") {
515 el = el.parentNode;
516 }
517 return el;
518 }
519 }, {
520 key: "_initDropdownListeners",
521 value: function _initDropdownListeners() {
522 var _this4 = this;
523 // hack for input nested inside label (which is valid markup): clicking the selected-flag to
524 // open the dropdown would then automatically trigger a 2nd click on the input which would
525 // close it again
526 this._handleLabelClick = function(e) {
527 // if the dropdown is closed, then focus the input, else ignore the click
528 if (_this4.countryList.classList.contains("iti__hide")) _this4.telInput.focus(); else e.preventDefault();
529 };
530 var label = this._getClosestLabel();
531 if (label) label.addEventListener("click", this._handleLabelClick);
532 // toggle country dropdown on click
533 this._handleClickSelectedFlag = function() {
534 // only intercept this event if we're opening the dropdown
535 // else let it bubble up to the top ("click-off-to-close" listener)
536 // we cannot just stopPropagation as it may be needed to close another instance
537 if (_this4.countryList.classList.contains("iti__hide") && !_this4.telInput.disabled && !_this4.telInput.readOnly) {
538 _this4._showDropdown();
539 }
540 };
541 this.selectedFlag.addEventListener("click", this._handleClickSelectedFlag);
542 // open dropdown list if currently focused
543 this._handleFlagsContainerKeydown = function(e) {
544 var isDropdownHidden = _this4.countryList.classList.contains("iti__hide");
545 if (isDropdownHidden && [ "ArrowUp", "Up", "ArrowDown", "Down", " ", "Enter" ].indexOf(e.key) !== -1) {
546 // prevent form from being submitted if "ENTER" was pressed
547 e.preventDefault();
548 // prevent event from being handled again by document
549 e.stopPropagation();
550 _this4._showDropdown();
551 }
552 // allow navigation from dropdown to input on TAB
553 if (e.key === "Tab") _this4._closeDropdown();
554 };
555 this.flagsContainer.addEventListener("keydown", this._handleFlagsContainerKeydown);
556 }
557 }, {
558 key: "_initRequests",
559 value: function _initRequests() {
560 var _this5 = this;
561 // if the user has specified the path to the utils script, fetch it on window.load, else resolve
562 if (this.options.utilsScript && !window.intlTelInputUtils) {
563 // if the plugin is being initialised after the window.load event has already been fired
564 if (window.intlTelInputGlobals.windowLoaded) {
565 window.intlTelInputGlobals.loadUtils(this.options.utilsScript);
566 } else {
567 // wait until the load event so we don't block any other requests e.g. the flags image
568 window.addEventListener("load", function() {
569 window.intlTelInputGlobals.loadUtils(_this5.options.utilsScript);
570 });
571 }
572 } else this.resolveUtilsScriptPromise();
573 if (this.options.initialCountry === "auto") this._loadAutoCountry(); else this.resolveAutoCountryPromise();
574 }
575 }, {
576 key: "_loadAutoCountry",
577 value: function _loadAutoCountry() {
578 // 3 options:
579 // 1) already loaded (we're done)
580 // 2) not already started loading (start)
581 // 3) already started loading (do nothing - just wait for loading callback to fire)
582 if (window.intlTelInputGlobals.autoCountry) {
583 this.handleAutoCountry();
584 } else if (!window.intlTelInputGlobals.startedLoadingAutoCountry) {
585 // don't do this twice!
586 window.intlTelInputGlobals.startedLoadingAutoCountry = true;
587 if (typeof this.options.geoIpLookup === "function") {
588 this.options.geoIpLookup(function(countryCode) {
589 window.intlTelInputGlobals.autoCountry = countryCode.toLowerCase();
590 // tell all instances the auto country is ready
591 // TODO: this should just be the current instances
592 // UPDATE: use setTimeout in case their geoIpLookup function calls this callback straight
593 // away (e.g. if they have already done the geo ip lookup somewhere else). Using
594 // setTimeout means that the current thread of execution will finish before executing
595 // this, which allows the plugin to finish initialising.
596 setTimeout(function() {
597 return forEachInstance("handleAutoCountry");
598 });
599 }, function() {
600 return forEachInstance("rejectAutoCountryPromise");
601 });
602 }
603 }
604 }
605 }, {
606 key: "_initKeyListeners",
607 value: function _initKeyListeners() {
608 var _this6 = this;
609 // update flag on keyup
610 this._handleKeyupEvent = function() {
611 if (_this6._updateFlagFromNumber(_this6.telInput.value)) {
612 _this6._triggerCountryChange();
613 }
614 };
615 this.telInput.addEventListener("keyup", this._handleKeyupEvent);
616 // update flag on cut/paste events (now supported in all major browsers)
617 this._handleClipboardEvent = function() {
618 // hack because "paste" event is fired before input is updated
619 setTimeout(_this6._handleKeyupEvent);
620 };
621 this.telInput.addEventListener("cut", this._handleClipboardEvent);
622 this.telInput.addEventListener("paste", this._handleClipboardEvent);
623 }
624 }, {
625 key: "_cap",
626 value: function _cap(number) {
627 var max = this.telInput.getAttribute("maxlength");
628 return max && number.length > max ? number.substr(0, max) : number;
629 }
630 }, {
631 key: "_initBlurListeners",
632 value: function _initBlurListeners() {
633 var _this7 = this;
634 // on blur or form submit: if just a dial code then remove it
635 this._handleSubmitOrBlurEvent = function() {
636 _this7._removeEmptyDialCode();
637 };
638 if (this.telInput.form) this.telInput.form.addEventListener("submit", this._handleSubmitOrBlurEvent);
639 this.telInput.addEventListener("blur", this._handleSubmitOrBlurEvent);
640 }
641 }, {
642 key: "_removeEmptyDialCode",
643 value: function _removeEmptyDialCode() {
644 if (this.telInput.value.charAt(0) === "+") {
645 var numeric = this._getNumeric(this.telInput.value);
646 // if just a plus, or if just a dial code
647 if (!numeric || this.selectedCountryData.dialCode === numeric) {
648 this.telInput.value = "";
649 }
650 }
651 }
652 }, {
653 key: "_getNumeric",
654 value: function _getNumeric(s) {
655 return s.replace(/\D/g, "");
656 }
657 }, {
658 key: "_trigger",
659 value: function _trigger(name) {
660 // have to use old school document.createEvent as IE11 doesn't support `new Event()` syntax
661 var e = document.createEvent("Event");
662 e.initEvent(name, true, true);
663 // can bubble, and is cancellable
664 this.telInput.dispatchEvent(e);
665 }
666 }, {
667 key: "_showDropdown",
668 value: function _showDropdown() {
669 this.countryList.classList.remove("iti__hide");
670 this.selectedFlag.setAttribute("aria-expanded", "true");
671 this._setDropdownPosition();
672 // update highlighting and scroll to active list item
673 if (this.activeItem) {
674 this._highlightListItem(this.activeItem, false);
675 this._scrollTo(this.activeItem, true);
676 }
677 // bind all the dropdown-related listeners: mouseover, click, click-off, keydown
678 this._bindDropdownListeners();
679 // update the arrow
680 this.dropdownArrow.classList.add("iti__arrow--up");
681 this._trigger("open:countrydropdown");
682 }
683 }, {
684 key: "_toggleClass",
685 value: function _toggleClass(el, className, shouldHaveClass) {
686 if (shouldHaveClass && !el.classList.contains(className)) el.classList.add(className); else if (!shouldHaveClass && el.classList.contains(className)) el.classList.remove(className);
687 }
688 }, {
689 key: "_setDropdownPosition",
690 value: function _setDropdownPosition() {
691 var _this8 = this;
692 if (this.options.dropdownContainer) {
693 this.options.dropdownContainer.appendChild(this.dropdown);
694 }
695 if (!this.isMobile) {
696 var pos = this.telInput.getBoundingClientRect();
697 // windowTop from https://stackoverflow.com/a/14384091/217866
698 var windowTop = window.pageYOffset || document.documentElement.scrollTop;
699 var inputTop = pos.top + windowTop;
700 var dropdownHeight = this.countryList.offsetHeight;
701 // dropdownFitsBelow = (dropdownBottom < windowBottom)
702 var dropdownFitsBelow = inputTop + this.telInput.offsetHeight + dropdownHeight < windowTop + window.innerHeight;
703 var dropdownFitsAbove = inputTop - dropdownHeight > windowTop;
704 // by default, the dropdown will be below the input. If we want to position it above the
705 // input, we add the dropup class.
706 this._toggleClass(this.countryList, "iti__country-list--dropup", !dropdownFitsBelow && dropdownFitsAbove);
707 // if dropdownContainer is enabled, calculate postion
708 if (this.options.dropdownContainer) {
709 // by default the dropdown will be directly over the input because it's not in the flow.
710 // If we want to position it below, we need to add some extra top value.
711 var extraTop = !dropdownFitsBelow && dropdownFitsAbove ? 0 : this.telInput.offsetHeight;
712 // calculate placement
713 this.dropdown.style.top = "".concat(inputTop + extraTop, "px");
714 this.dropdown.style.left = "".concat(pos.left + document.body.scrollLeft, "px");
715 // close menu on window scroll
716 this._handleWindowScroll = function() {
717 return _this8._closeDropdown();
718 };
719 window.addEventListener("scroll", this._handleWindowScroll);
720 }
721 }
722 }
723 }, {
724 key: "_getClosestListItem",
725 value: function _getClosestListItem(target) {
726 var el = target;
727 while (el && el !== this.countryList && !el.classList.contains("iti__country")) {
728 el = el.parentNode;
729 }
730 // if we reached the countryList element, then return null
731 return el === this.countryList ? null : el;
732 }
733 }, {
734 key: "_bindDropdownListeners",
735 value: function _bindDropdownListeners() {
736 var _this9 = this;
737 // when mouse over a list item, just highlight that one
738 // we add the class "highlight", so if they hit "enter" we know which one to select
739 this._handleMouseoverCountryList = function(e) {
740 // handle event delegation, as we're listening for this event on the countryList
741 var listItem = _this9._getClosestListItem(e.target);
742 if (listItem) _this9._highlightListItem(listItem, false);
743 };
744 this.countryList.addEventListener("mouseover", this._handleMouseoverCountryList);
745 // listen for country selection
746 this._handleClickCountryList = function(e) {
747 var listItem = _this9._getClosestListItem(e.target);
748 if (listItem) _this9._selectListItem(listItem);
749 };
750 this.countryList.addEventListener("click", this._handleClickCountryList);
751 // click off to close
752 // (except when this initial opening click is bubbling up)
753 // we cannot just stopPropagation as it may be needed to close another instance
754 var isOpening = true;
755 this._handleClickOffToClose = function() {
756 if (!isOpening) _this9._closeDropdown();
757 isOpening = false;
758 };
759 document.documentElement.addEventListener("click", this._handleClickOffToClose);
760 // listen for up/down scrolling, enter to select, or letters to jump to country name.
761 // use keydown as keypress doesn't fire for non-char keys and we want to catch if they
762 // just hit down and hold it to scroll down (no keyup event).
763 // listen on the document because that's where key events are triggered if no input has focus
764 var query = "";
765 var queryTimer = null;
766 this._handleKeydownOnDropdown = function(e) {
767 // prevent down key from scrolling the whole page,
768 // and enter key from submitting a form etc
769 e.preventDefault();
770 // up and down to navigate
771 if (e.key === "ArrowUp" || e.key === "Up" || e.key === "ArrowDown" || e.key === "Down") _this9._handleUpDownKey(e.key); else if (e.key === "Enter") _this9._handleEnterKey(); else if (e.key === "Escape") _this9._closeDropdown(); else if (/^[a-zA-ZÀ-ÿа-яА-Я ]$/.test(e.key)) {
772 // jump to countries that start with the query string
773 if (queryTimer) clearTimeout(queryTimer);
774 query += e.key.toLowerCase();
775 _this9._searchForCountry(query);
776 // if the timer hits 1 second, reset the query
777 queryTimer = setTimeout(function() {
778 query = "";
779 }, 1e3);
780 }
781 };
782 document.addEventListener("keydown", this._handleKeydownOnDropdown);
783 }
784 }, {
785 key: "_handleUpDownKey",
786 value: function _handleUpDownKey(key) {
787 var next = key === "ArrowUp" || key === "Up" ? this.highlightedItem.previousElementSibling : this.highlightedItem.nextElementSibling;
788 if (next) {
789 // skip the divider
790 if (next.classList.contains("iti__divider")) {
791 next = key === "ArrowUp" || key === "Up" ? next.previousElementSibling : next.nextElementSibling;
792 }
793 this._highlightListItem(next, true);
794 }
795 }
796 }, {
797 key: "_handleEnterKey",
798 value: function _handleEnterKey() {
799 if (this.highlightedItem) this._selectListItem(this.highlightedItem);
800 }
801 }, {
802 key: "_searchForCountry",
803 value: function _searchForCountry(query) {
804 for (var i = 0; i < this.countries.length; i++) {
805 if (this._startsWith(this.countries[i].name, query)) {
806 var listItem = this.countryList.querySelector("#iti-".concat(this.id, "__item-").concat(this.countries[i].iso2));
807 // update highlighting and scroll
808 this._highlightListItem(listItem, false);
809 this._scrollTo(listItem, true);
810 break;
811 }
812 }
813 }
814 }, {
815 key: "_startsWith",
816 value: function _startsWith(a, b) {
817 return a.substr(0, b.length).toLowerCase() === b;
818 }
819 }, {
820 key: "_updateValFromNumber",
821 value: function _updateValFromNumber(originalNumber) {
822 var number = originalNumber;
823 if (this.options.formatOnDisplay && window.intlTelInputUtils && this.selectedCountryData) {
824 var useNational = !this.options.separateDialCode && (this.options.nationalMode || number.charAt(0) !== "+");
825 var _intlTelInputUtils$nu = intlTelInputUtils.numberFormat, NATIONAL = _intlTelInputUtils$nu.NATIONAL, INTERNATIONAL = _intlTelInputUtils$nu.INTERNATIONAL;
826 var format = useNational ? NATIONAL : INTERNATIONAL;
827 number = intlTelInputUtils.formatNumber(number, this.selectedCountryData.iso2, format);
828 }
829 number = this._beforeSetNumber(number);
830 this.telInput.value = number;
831 }
832 }, {
833 key: "_updateFlagFromNumber",
834 value: function _updateFlagFromNumber(originalNumber) {
835 // if we're in nationalMode and we already have US/Canada selected, make sure the number starts
836 // with a +1 so _getDialCode will be able to extract the area code
837 // update: if we dont yet have selectedCountryData, but we're here (trying to update the flag
838 // from the number), that means we're initialising the plugin with a number that already has a
839 // dial code, so fine to ignore this bit
840 var number = originalNumber;
841 var selectedDialCode = this.selectedCountryData.dialCode;
842 var isNanp = selectedDialCode === "1";
843 if (number && this.options.nationalMode && isNanp && number.charAt(0) !== "+") {
844 if (number.charAt(0) !== "1") number = "1".concat(number);
845 number = "+".concat(number);
846 }
847 // update flag if user types area code for another country
848 if (this.options.separateDialCode && selectedDialCode && number.charAt(0) !== "+") {
849 number = "+".concat(selectedDialCode).concat(number);
850 }
851 // try and extract valid dial code from input
852 var dialCode = this._getDialCode(number);
853 var numeric = this._getNumeric(number);
854 var countryCode = null;
855 if (dialCode) {
856 var countryCodes = this.countryCodes[this._getNumeric(dialCode)];
857 // check if the right country is already selected. this should be false if the number is
858 // longer than the matched dial code because in this case we need to make sure that if
859 // there are multiple country matches, that the first one is selected (note: we could
860 // just check that here, but it requires the same loop that we already have later)
861 var alreadySelected = countryCodes.indexOf(this.selectedCountryData.iso2) !== -1 && numeric.length <= dialCode.length - 1;
862 var isRegionlessNanpNumber = selectedDialCode === "1" && this._isRegionlessNanp(numeric);
863 // only update the flag if:
864 // A) NOT (we currently have a NANP flag selected, and the number is a regionlessNanp)
865 // AND
866 // B) the right country is not already selected
867 if (!isRegionlessNanpNumber && !alreadySelected) {
868 // if using onlyCountries option, countryCodes[0] may be empty, so we must find the first
869 // non-empty index
870 for (var j = 0; j < countryCodes.length; j++) {
871 if (countryCodes[j]) {
872 countryCode = countryCodes[j];
873 break;
874 }
875 }
876 }
877 } else if (number.charAt(0) === "+" && numeric.length) {
878 // invalid dial code, so empty
879 // Note: use getNumeric here because the number has not been formatted yet, so could contain
880 // bad chars
881 countryCode = "";
882 } else if (!number || number === "+") {
883 // empty, or just a plus, so default
884 countryCode = this.defaultCountry;
885 }
886 if (countryCode !== null) {
887 return this._setFlag(countryCode);
888 }
889 return false;
890 }
891 }, {
892 key: "_isRegionlessNanp",
893 value: function _isRegionlessNanp(number) {
894 var numeric = this._getNumeric(number);
895 if (numeric.charAt(0) === "1") {
896 var areaCode = numeric.substr(1, 3);
897 return regionlessNanpNumbers.indexOf(areaCode) !== -1;
898 }
899 return false;
900 }
901 }, {
902 key: "_highlightListItem",
903 value: function _highlightListItem(listItem, shouldFocus) {
904 var prevItem = this.highlightedItem;
905 if (prevItem) prevItem.classList.remove("iti__highlight");
906 this.highlightedItem = listItem;
907 this.highlightedItem.classList.add("iti__highlight");
908 if (shouldFocus) this.highlightedItem.focus();
909 }
910 }, {
911 key: "_getCountryData",
912 value: function _getCountryData(countryCode, ignoreOnlyCountriesOption, allowFail) {
913 var countryList = ignoreOnlyCountriesOption ? allCountries : this.countries;
914 for (var i = 0; i < countryList.length; i++) {
915 if (countryList[i].iso2 === countryCode) {
916 return countryList[i];
917 }
918 }
919 if (allowFail) {
920 return null;
921 }
922 throw new Error("No country data for '".concat(countryCode, "'"));
923 }
924 }, {
925 key: "_setFlag",
926 value: function _setFlag(countryCode) {
927 var prevCountry = this.selectedCountryData.iso2 ? this.selectedCountryData : {};
928 // do this first as it will throw an error and stop if countryCode is invalid
929 this.selectedCountryData = countryCode ? this._getCountryData(countryCode, false, false) : {};
930 // update the defaultCountry - we only need the iso2 from now on, so just store that
931 if (this.selectedCountryData.iso2) {
932 this.defaultCountry = this.selectedCountryData.iso2;
933 }
934 this.selectedFlagInner.setAttribute("class", "iti__flag iti__".concat(countryCode));
935 // update the selected country's title attribute
936 var title = countryCode ? "".concat(this.selectedCountryData.name, ": +").concat(this.selectedCountryData.dialCode) : "Unknown";
937 this.selectedFlag.setAttribute("title", title);
938 if (this.options.separateDialCode) {
939 var dialCode = this.selectedCountryData.dialCode ? "+".concat(this.selectedCountryData.dialCode) : "";
940 this.selectedDialCode.innerHTML = dialCode;
941 // offsetWidth is zero if input is in a hidden container during initialisation
942 var selectedFlagWidth = this.selectedFlag.offsetWidth || this._getHiddenSelectedFlagWidth();
943 // add 6px of padding after the grey selected-dial-code box, as this is what we use in the css
944 this.telInput.style.paddingLeft = "".concat(selectedFlagWidth + 6, "px");
945 }
946 // and the input's placeholder
947 this._updatePlaceholder();
948 // update the active list item
949 if (this.options.allowDropdown) {
950 var prevItem = this.activeItem;
951 if (prevItem) {
952 prevItem.classList.remove("iti__active");
953 prevItem.setAttribute("aria-selected", "false");
954 }
955 if (countryCode) {
956 // check if there is a preferred item first, else fall back to standard
957 var nextItem = this.countryList.querySelector("#iti-".concat(this.id, "__item-").concat(countryCode, "-preferred")) || this.countryList.querySelector("#iti-".concat(this.id, "__item-").concat(countryCode));
958 nextItem.setAttribute("aria-selected", "true");
959 nextItem.classList.add("iti__active");
960 this.activeItem = nextItem;
961 this.selectedFlag.setAttribute("aria-activedescendant", nextItem.getAttribute("id"));
962 }
963 }
964 // return if the flag has changed or not
965 return prevCountry.iso2 !== countryCode;
966 }
967 }, {
968 key: "_getHiddenSelectedFlagWidth",
969 value: function _getHiddenSelectedFlagWidth() {
970 // to get the right styling to apply, all we need is a shallow clone of the container,
971 // and then to inject a deep clone of the selectedFlag element
972 var containerClone = this.telInput.parentNode.cloneNode();
973 containerClone.style.visibility = "hidden";
974 document.body.appendChild(containerClone);
975 var selectedFlagClone = this.selectedFlag.cloneNode(true);
976 containerClone.appendChild(selectedFlagClone);
977 var width = selectedFlagClone.offsetWidth;
978 containerClone.parentNode.removeChild(containerClone);
979 return width;
980 }
981 }, {
982 key: "_updatePlaceholder",
983 value: function _updatePlaceholder() {
984 var shouldSetPlaceholder = this.options.autoPlaceholder === "aggressive" || !this.hadInitialPlaceholder && this.options.autoPlaceholder === "polite";
985 if (window.intlTelInputUtils && shouldSetPlaceholder) {
986 var numberType = intlTelInputUtils.numberType[this.options.placeholderNumberType];
987 var placeholder = this.selectedCountryData.iso2 ? intlTelInputUtils.getExampleNumber(this.selectedCountryData.iso2, this.options.nationalMode, numberType) : "";
988 placeholder = this._beforeSetNumber(placeholder);
989 if (typeof this.options.customPlaceholder === "function") {
990 placeholder = this.options.customPlaceholder(placeholder, this.selectedCountryData);
991 }
992 this.telInput.setAttribute("placeholder", placeholder);
993 }
994 }
995 }, {
996 key: "_selectListItem",
997 value: function _selectListItem(listItem) {
998 // update selected flag and active list item
999 var flagChanged = this._setFlag(listItem.getAttribute("data-country-code"));
1000 this._closeDropdown();
1001 this._updateDialCode(listItem.getAttribute("data-dial-code"), true);
1002 // focus the input
1003 this.telInput.focus();
1004 // put cursor at end - this fix is required for FF and IE11 (with nationalMode=false i.e. auto
1005 // inserting dial code), who try to put the cursor at the beginning the first time
1006 var len = this.telInput.value.length;
1007 this.telInput.setSelectionRange(len, len);
1008 if (flagChanged) {
1009 this._triggerCountryChange();
1010 }
1011 }
1012 }, {
1013 key: "_closeDropdown",
1014 value: function _closeDropdown() {
1015 this.countryList.classList.add("iti__hide");
1016 this.selectedFlag.setAttribute("aria-expanded", "false");
1017 // update the arrow
1018 this.dropdownArrow.classList.remove("iti__arrow--up");
1019 // unbind key events
1020 document.removeEventListener("keydown", this._handleKeydownOnDropdown);
1021 document.documentElement.removeEventListener("click", this._handleClickOffToClose);
1022 this.countryList.removeEventListener("mouseover", this._handleMouseoverCountryList);
1023 this.countryList.removeEventListener("click", this._handleClickCountryList);
1024 // remove menu from container
1025 if (this.options.dropdownContainer) {
1026 if (!this.isMobile) window.removeEventListener("scroll", this._handleWindowScroll);
1027 if (this.dropdown.parentNode) this.dropdown.parentNode.removeChild(this.dropdown);
1028 }
1029 this._trigger("close:countrydropdown");
1030 }
1031 }, {
1032 key: "_scrollTo",
1033 value: function _scrollTo(element, middle) {
1034 var container = this.countryList;
1035 // windowTop from https://stackoverflow.com/a/14384091/217866
1036 var windowTop = window.pageYOffset || document.documentElement.scrollTop;
1037 var containerHeight = container.offsetHeight;
1038 var containerTop = container.getBoundingClientRect().top + windowTop;
1039 var containerBottom = containerTop + containerHeight;
1040 var elementHeight = element.offsetHeight;
1041 var elementTop = element.getBoundingClientRect().top + windowTop;
1042 var elementBottom = elementTop + elementHeight;
1043 var newScrollTop = elementTop - containerTop + container.scrollTop;
1044 var middleOffset = containerHeight / 2 - elementHeight / 2;
1045 if (elementTop < containerTop) {
1046 // scroll up
1047 if (middle) newScrollTop -= middleOffset;
1048 container.scrollTop = newScrollTop;
1049 } else if (elementBottom > containerBottom) {
1050 // scroll down
1051 if (middle) newScrollTop += middleOffset;
1052 var heightDifference = containerHeight - elementHeight;
1053 container.scrollTop = newScrollTop - heightDifference;
1054 }
1055 }
1056 }, {
1057 key: "_updateDialCode",
1058 value: function _updateDialCode(newDialCodeBare, hasSelectedListItem) {
1059 var inputVal = this.telInput.value;
1060 // save having to pass this every time
1061 var newDialCode = "+".concat(newDialCodeBare);
1062 var newNumber;
1063 if (inputVal.charAt(0) === "+") {
1064 // there's a plus so we're dealing with a replacement (doesn't matter if nationalMode or not)
1065 var prevDialCode = this._getDialCode(inputVal);
1066 if (prevDialCode) {
1067 // current number contains a valid dial code, so replace it
1068 newNumber = inputVal.replace(prevDialCode, newDialCode);
1069 } else {
1070 // current number contains an invalid dial code, so ditch it
1071 // (no way to determine where the invalid dial code ends and the rest of the number begins)
1072 newNumber = newDialCode;
1073 }
1074 } else if (this.options.nationalMode || this.options.separateDialCode) {
1075 // don't do anything
1076 return;
1077 } else {
1078 // nationalMode is disabled
1079 if (inputVal) {
1080 // there is an existing value with no dial code: prefix the new dial code
1081 newNumber = newDialCode + inputVal;
1082 } else if (hasSelectedListItem || !this.options.autoHideDialCode) {
1083 // no existing value and either they've just selected a list item, or autoHideDialCode is
1084 // disabled: insert new dial code
1085 newNumber = newDialCode;
1086 } else {
1087 return;
1088 }
1089 }
1090 this.telInput.value = newNumber;
1091 }
1092 }, {
1093 key: "_getDialCode",
1094 value: function _getDialCode(number) {
1095 var dialCode = "";
1096 // only interested in international numbers (starting with a plus)
1097 if (number.charAt(0) === "+") {
1098 var numericChars = "";
1099 // iterate over chars
1100 for (var i = 0; i < number.length; i++) {
1101 var c = number.charAt(i);
1102 // if char is number (https://stackoverflow.com/a/8935649/217866)
1103 if (!isNaN(parseInt(c, 10))) {
1104 numericChars += c;
1105 // if current numericChars make a valid dial code
1106 if (this.countryCodes[numericChars]) {
1107 // store the actual raw string (useful for matching later)
1108 dialCode = number.substr(0, i + 1);
1109 }
1110 if (numericChars.length === this.dialCodeMaxLen) {
1111 break;
1112 }
1113 }
1114 }
1115 }
1116 return dialCode;
1117 }
1118 }, {
1119 key: "_getFullNumber",
1120 value: function _getFullNumber() {
1121 var val = this.telInput.value.trim();
1122 var dialCode = this.selectedCountryData.dialCode;
1123 var prefix;
1124 var numericVal = this._getNumeric(val);
1125 if (this.options.separateDialCode && val.charAt(0) !== "+" && dialCode && numericVal) {
1126 // when using separateDialCode, it is visible so is effectively part of the typed number
1127 prefix = "+".concat(dialCode);
1128 } else {
1129 prefix = "";
1130 }
1131 return prefix + val;
1132 }
1133 }, {
1134 key: "_beforeSetNumber",
1135 value: function _beforeSetNumber(originalNumber) {
1136 var number = originalNumber;
1137 if (this.options.separateDialCode) {
1138 var dialCode = this._getDialCode(number);
1139 // if there is a valid dial code
1140 if (dialCode) {
1141 // in case _getDialCode returned an area code as well
1142 dialCode = "+".concat(this.selectedCountryData.dialCode);
1143 // a lot of numbers will have a space separating the dial code and the main number, and
1144 // some NANP numbers will have a hyphen e.g. +1 684-733-1234 - in both cases we want to get
1145 // rid of it
1146 // NOTE: don't just trim all non-numerics as may want to preserve an open parenthesis etc
1147 var start = number[dialCode.length] === " " || number[dialCode.length] === "-" ? dialCode.length + 1 : dialCode.length;
1148 number = number.substr(start);
1149 }
1150 }
1151 return this._cap(number);
1152 }
1153 }, {
1154 key: "_triggerCountryChange",
1155 value: function _triggerCountryChange() {
1156 this._trigger("countrychange");
1157 }
1158 }, {
1159 key: "handleAutoCountry",
1160 value: function handleAutoCountry() {
1161 if (this.options.initialCountry === "auto") {
1162 // we must set this even if there is an initial val in the input: in case the initial val is
1163 // invalid and they delete it - they should see their auto country
1164 this.defaultCountry = window.intlTelInputGlobals.autoCountry;
1165 // if there's no initial value in the input, then update the flag
1166 if (!this.telInput.value) {
1167 this.setCountry(this.defaultCountry);
1168 }
1169 this.resolveAutoCountryPromise();
1170 }
1171 }
1172 }, {
1173 key: "handleUtils",
1174 value: function handleUtils() {
1175 // if the request was successful
1176 if (window.intlTelInputUtils) {
1177 // if there's an initial value in the input, then format it
1178 if (this.telInput.value) {
1179 this._updateValFromNumber(this.telInput.value);
1180 }
1181 this._updatePlaceholder();
1182 }
1183 this.resolveUtilsScriptPromise();
1184 }
1185 }, {
1186 key: "destroy",
1187 value: function destroy() {
1188 var form = this.telInput.form;
1189 if (this.options.allowDropdown) {
1190 // make sure the dropdown is closed (and unbind listeners)
1191 this._closeDropdown();
1192 this.selectedFlag.removeEventListener("click", this._handleClickSelectedFlag);
1193 this.flagsContainer.removeEventListener("keydown", this._handleFlagsContainerKeydown);
1194 // label click hack
1195 var label = this._getClosestLabel();
1196 if (label) label.removeEventListener("click", this._handleLabelClick);
1197 }
1198 // unbind hiddenInput listeners
1199 if (this.hiddenInput && form) form.removeEventListener("submit", this._handleHiddenInputSubmit);
1200 // unbind autoHideDialCode listeners
1201 if (this.options.autoHideDialCode) {
1202 if (form) form.removeEventListener("submit", this._handleSubmitOrBlurEvent);
1203 this.telInput.removeEventListener("blur", this._handleSubmitOrBlurEvent);
1204 }
1205 // unbind key events, and cut/paste events
1206 this.telInput.removeEventListener("keyup", this._handleKeyupEvent);
1207 this.telInput.removeEventListener("cut", this._handleClipboardEvent);
1208 this.telInput.removeEventListener("paste", this._handleClipboardEvent);
1209 // remove attribute of id instance: data-intl-tel-input-id
1210 this.telInput.removeAttribute("data-intl-tel-input-id");
1211 // remove markup (but leave the original input)
1212 var wrapper = this.telInput.parentNode;
1213 wrapper.parentNode.insertBefore(this.telInput, wrapper);
1214 wrapper.parentNode.removeChild(wrapper);
1215 delete window.intlTelInputGlobals.instances[this.id];
1216 }
1217 }, {
1218 key: "getExtension",
1219 value: function getExtension() {
1220 if (window.intlTelInputUtils) {
1221 return intlTelInputUtils.getExtension(this._getFullNumber(), this.selectedCountryData.iso2);
1222 }
1223 return "";
1224 }
1225 }, {
1226 key: "getNumber",
1227 value: function getNumber(format) {
1228 if (window.intlTelInputUtils) {
1229 var iso2 = this.selectedCountryData.iso2;
1230 return intlTelInputUtils.formatNumber(this._getFullNumber(), iso2, format);
1231 }
1232 return "";
1233 }
1234 }, {
1235 key: "getNumberType",
1236 value: function getNumberType() {
1237 if (window.intlTelInputUtils) {
1238 return intlTelInputUtils.getNumberType(this._getFullNumber(), this.selectedCountryData.iso2);
1239 }
1240 return -99;
1241 }
1242 }, {
1243 key: "getSelectedCountryData",
1244 value: function getSelectedCountryData() {
1245 return this.selectedCountryData;
1246 }
1247 }, {
1248 key: "getValidationError",
1249 value: function getValidationError() {
1250 if (window.intlTelInputUtils) {
1251 var iso2 = this.selectedCountryData.iso2;
1252 return intlTelInputUtils.getValidationError(this._getFullNumber(), iso2);
1253 }
1254 return -99;
1255 }
1256 }, {
1257 key: "isValidNumber",
1258 value: function isValidNumber() {
1259 var val = this._getFullNumber().trim();
1260 var countryCode = this.options.nationalMode ? this.selectedCountryData.iso2 : "";
1261 return window.intlTelInputUtils ? intlTelInputUtils.isValidNumber(val, countryCode) : null;
1262 }
1263 }, {
1264 key: "setCountry",
1265 value: function setCountry(originalCountryCode) {
1266 var countryCode = originalCountryCode.toLowerCase();
1267 // check if already selected
1268 if (!this.selectedFlagInner.classList.contains("iti__".concat(countryCode))) {
1269 this._setFlag(countryCode);
1270 this._updateDialCode(this.selectedCountryData.dialCode, false);
1271 this._triggerCountryChange();
1272 }
1273 }
1274 }, {
1275 key: "setNumber",
1276 value: function setNumber(number) {
1277 // we must update the flag first, which updates this.selectedCountryData, which is used for
1278 // formatting the number before displaying it
1279 var flagChanged = this._updateFlagFromNumber(number);
1280 this._updateValFromNumber(number);
1281 if (flagChanged) {
1282 this._triggerCountryChange();
1283 }
1284 }
1285 }, {
1286 key: "setPlaceholderNumberType",
1287 value: function setPlaceholderNumberType(type) {
1288 this.options.placeholderNumberType = type;
1289 this._updatePlaceholder();
1290 }
1291 } ]);
1292 return Iti;
1293 }();
1294 /********************
1295 * STATIC METHODS
1296 ********************/
1297 // get the country data object
1298 intlTelInputGlobals.getCountryData = function() {
1299 return allCountries;
1300 };
1301 // inject a <script> element to load utils.js
1302 var injectScript = function injectScript(path, handleSuccess, handleFailure) {
1303 // inject a new script element into the page
1304 var script = document.createElement("script");
1305 script.onload = function() {
1306 forEachInstance("handleUtils");
1307 if (handleSuccess) handleSuccess();
1308 };
1309 script.onerror = function() {
1310 forEachInstance("rejectUtilsScriptPromise");
1311 if (handleFailure) handleFailure();
1312 };
1313 script.className = "iti-load-utils";
1314 script.async = true;
1315 script.src = path;
1316 document.body.appendChild(script);
1317 };
1318 // load the utils script
1319 intlTelInputGlobals.loadUtils = function(path) {
1320 // 2 options:
1321 // 1) not already started loading (start)
1322 // 2) already started loading (do nothing - just wait for the onload callback to fire, which will
1323 // trigger handleUtils on all instances, invoking their resolveUtilsScriptPromise functions)
1324 if (!window.intlTelInputUtils && !window.intlTelInputGlobals.startedLoadingUtilsScript) {
1325 // only do this once
1326 window.intlTelInputGlobals.startedLoadingUtilsScript = true;
1327 // if we have promises, then return a promise
1328 if (typeof Promise !== "undefined") {
1329 return new Promise(function(resolve, reject) {
1330 return injectScript(path, resolve, reject);
1331 });
1332 }
1333 injectScript(path);
1334 }
1335 return null;
1336 };
1337 // default options
1338 intlTelInputGlobals.defaults = defaults;
1339 // version
1340 intlTelInputGlobals.version = "17.0.0";
1341 var pluginName = "intlTelInput";
1342 // A really lightweight plugin wrapper around the constructor,
1343 // preventing against multiple instantiations
1344 $.fn[pluginName] = function(options) {
1345 var args = arguments;
1346 // Is the first parameter an object (options), or was omitted, instantiate a new instance of the plugin.
1347 if (options === undefined || typeof options === "object") {
1348 return this.each(function() {
1349 if (!$.data(this, "plugin_" + pluginName)) {
1350 var iti = new Iti(this, options);
1351 iti._init();
1352 window.intlTelInputGlobals.instances[iti.id] = iti;
1353 $.data(this, "plugin_" + pluginName, iti);
1354 }
1355 });
1356 } else if (typeof options === "string" && options[0] !== "_") {
1357 // If the first parameter is a string and it doesn't start with an underscore treat this as a call to a public method.
1358 // Cache the method call to make it possible to return a value
1359 var returns;
1360 this.each(function() {
1361 var instance = $.data(this, "plugin_" + pluginName);
1362 // Tests that there's already a plugin-instance and checks that the requested public method exists
1363 if (instance instanceof Iti && typeof instance[options] === "function") {
1364 // Call the method of our plugin instance, and pass it the supplied arguments.
1365 returns = instance[options].apply(instance, Array.prototype.slice.call(args, 1));
1366 }
1367 // Allow instances to be destroyed via the 'destroy' method
1368 if (options === "destroy") $.data(this, "plugin_" + pluginName, null);
1369 });
1370 // If the earlier cached method gives a value back return the value, otherwise return this to preserve chainability.
1371 return returns !== undefined ? returns : this;
1372 }
1373 };
1374 });
1375