intl-tel-input 18.1.0 → 18.1.2

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.
Files changed (68) hide show
  1. package/.eslintrc +2 -8
  2. package/.github/CONTRIBUTING.md +1 -1
  3. package/.vscode/settings.json +7 -0
  4. package/CHANGELOG.md +3 -0
  5. package/Gruntfile.js +0 -2
  6. package/README.md +46 -35
  7. package/build/css/demo.css +16 -27
  8. package/build/css/intlTelInput.css +19 -9
  9. package/build/css/intlTelInput.min.css +1 -1
  10. package/build/js/data.js +2 -2
  11. package/build/js/data.min.js +2 -2
  12. package/build/js/intlTelInput-jquery.js +161 -60
  13. package/build/js/intlTelInput-jquery.min.js +3 -3
  14. package/build/js/intlTelInput.js +161 -60
  15. package/build/js/intlTelInput.min.js +3 -3
  16. package/composer.json +1 -1
  17. package/demo.html +42 -44
  18. package/demo_rtl.html +21 -23
  19. package/grunt/template.js +2 -265
  20. package/package.json +5 -2
  21. package/src/css/demo.scss +13 -29
  22. package/src/css/intlTelInput.scss +21 -21
  23. package/src/js/data.js +1 -1
  24. package/src/js/intlTelInput.js +563 -333
  25. package/examples/css/countrySync.css +0 -10
  26. package/examples/css/isValidNumber.css +0 -12
  27. package/examples/css/prism.css +0 -126
  28. package/examples/gen/country-sync.html +0 -98
  29. package/examples/gen/default-country-ip.html +0 -62
  30. package/examples/gen/display-number.html +0 -47
  31. package/examples/gen/hidden-input.html +0 -54
  32. package/examples/gen/init-promise.html +0 -66
  33. package/examples/gen/is-valid-number.html +0 -86
  34. package/examples/gen/js/countrySync.js +0 -31
  35. package/examples/gen/js/defaultCountryIp.js +0 -11
  36. package/examples/gen/js/displayNumber.js +0 -4
  37. package/examples/gen/js/hiddenInput.js +0 -5
  38. package/examples/gen/js/initPromise.js +0 -9
  39. package/examples/gen/js/isValidNumber.js +0 -37
  40. package/examples/gen/js/modifyCountryData.js +0 -11
  41. package/examples/gen/js/multipleInstances.js +0 -13
  42. package/examples/gen/js/nationalMode.js +0 -18
  43. package/examples/gen/js/onlyCountriesEurope.js +0 -8
  44. package/examples/gen/modify-country-data.html +0 -52
  45. package/examples/gen/multiple-instances.html +0 -60
  46. package/examples/gen/national-mode.html +0 -63
  47. package/examples/gen/only-countries-europe.html +0 -49
  48. package/examples/js/countrySync.js.ejs +0 -31
  49. package/examples/js/defaultCountryIp.js.ejs +0 -11
  50. package/examples/js/displayNumber.js.ejs +0 -4
  51. package/examples/js/hiddenInput.js.ejs +0 -5
  52. package/examples/js/initPromise.js.ejs +0 -9
  53. package/examples/js/isValidNumber.js.ejs +0 -37
  54. package/examples/js/modifyCountryData.js.ejs +0 -11
  55. package/examples/js/multipleInstances.js.ejs +0 -13
  56. package/examples/js/nationalMode.js.ejs +0 -18
  57. package/examples/js/onlyCountriesEurope.js.ejs +0 -8
  58. package/examples/js/prism.js +0 -11
  59. package/examples/partials/countrySync.html +0 -13
  60. package/examples/partials/defaultCountryIp.html +0 -5
  61. package/examples/partials/displayNumber.html +0 -1
  62. package/examples/partials/hiddenInput.html +0 -4
  63. package/examples/partials/initPromise.html +0 -8
  64. package/examples/partials/isValidNumber.html +0 -3
  65. package/examples/partials/multipleInstances.html +0 -3
  66. package/examples/partials/nationalMode.html +0 -2
  67. package/examples/partials/simpleInput.html +0 -1
  68. package/examples/template.html.ejs +0 -43
@@ -1,14 +1,16 @@
1
1
  const intlTelInputGlobals = {
2
2
  getInstance: (input) => {
3
- const id = input.getAttribute('data-intl-tel-input-id');
3
+ const id = input.getAttribute("data-intl-tel-input-id");
4
4
  return window.intlTelInputGlobals.instances[id];
5
5
  },
6
6
  instances: {},
7
7
  // using a global like this allows us to mock it in the tests
8
- documentReady: () => document.readyState === 'complete',
8
+ documentReady: () => document.readyState === "complete"
9
9
  };
10
10
 
11
- if (typeof window === 'object') window.intlTelInputGlobals = intlTelInputGlobals;
11
+ if (typeof window === "object") {
12
+ window.intlTelInputGlobals = intlTelInputGlobals;
13
+ }
12
14
 
13
15
  // these vars persist through all instances of the plugin
14
16
  let id = 0;
@@ -19,9 +21,9 @@ const defaults = {
19
21
  // also listen for blur/submit and auto remove dial code if that's all there is
20
22
  autoInsertDialCode: false,
21
23
  // add a placeholder in the input with an example number for the selected country
22
- autoPlaceholder: 'polite',
24
+ autoPlaceholder: "polite",
23
25
  // modify the parentClass
24
- customContainer: '',
26
+ customContainer: "",
25
27
  // modify the auto placeholder
26
28
  customPlaceholder: null,
27
29
  // append menu to specified element
@@ -33,29 +35,46 @@ const defaults = {
33
35
  // geoIp lookup function
34
36
  geoIpLookup: null,
35
37
  // inject a hidden input with this name, and on submit, populate it with the result of getNumber
36
- hiddenInput: '',
38
+ hiddenInput: "",
37
39
  // initial country
38
- initialCountry: '',
40
+ initialCountry: "",
39
41
  // localized country names e.g. { 'de': 'Deutschland' }
40
42
  localizedCountries: null,
41
- // deal with national numbers instead of international numbers
43
+ // national vs international formatting for numbers e.g. placeholders and displaying existing numbers
42
44
  nationalMode: true,
43
45
  // display only these countries
44
46
  onlyCountries: [],
45
47
  // number type to use for placeholders
46
- placeholderNumberType: 'MOBILE',
48
+ placeholderNumberType: "MOBILE",
47
49
  // the countries at the top of the list. defaults to united states and united kingdom
48
- preferredCountries: ['us', 'gb'],
50
+ preferredCountries: ["us", "gb"],
49
51
  // display the country dial code next to the selected flag
50
52
  separateDialCode: false,
51
53
  // option to hide the flags - must be used with separateDialCode, or allowDropdown=false
52
54
  showFlags: true,
53
55
  // specify the path to the libphonenumber script to enable validation/formatting
54
- utilsScript: '',
56
+ utilsScript: ""
55
57
  };
56
58
  // https://en.wikipedia.org/wiki/List_of_North_American_Numbering_Plan_area_codes#Non-geographic_area_codes
57
- const regionlessNanpNumbers = ['800', '822', '833', '844', '855', '866', '877', '880', '881', '882', '883', '884', '885', '886', '887', '888', '889'];
58
-
59
+ const regionlessNanpNumbers = [
60
+ "800",
61
+ "822",
62
+ "833",
63
+ "844",
64
+ "855",
65
+ "866",
66
+ "877",
67
+ "880",
68
+ "881",
69
+ "882",
70
+ "883",
71
+ "884",
72
+ "885",
73
+ "886",
74
+ "887",
75
+ "888",
76
+ "889"
77
+ ];
59
78
 
60
79
  // utility function to iterate over an object. can't use Object.entries or native forEach because
61
80
  // of IE11
@@ -66,7 +85,6 @@ const forEachProp = (obj, callback) => {
66
85
  }
67
86
  };
68
87
 
69
-
70
88
  // run a method on each instance of the plugin
71
89
  const forEachInstance = (method) => {
72
90
  forEachProp(window.intlTelInputGlobals.instances, (key) => {
@@ -74,7 +92,6 @@ const forEachInstance = (method) => {
74
92
  });
75
93
  };
76
94
 
77
-
78
95
  // this is our plugin class that we will create an instance of
79
96
  // eslint-disable-next-line no-unused-vars
80
97
  class Iti {
@@ -90,22 +107,29 @@ class Iti {
90
107
  const customOptions = options || {};
91
108
  this.options = {};
92
109
  forEachProp(defaults, (key, value) => {
93
- this.options[key] = (customOptions.hasOwnProperty(key)) ? customOptions[key] : value;
110
+ this.options[key] = customOptions.hasOwnProperty(key)
111
+ ? customOptions[key]
112
+ : value;
94
113
  });
95
114
 
96
- this.hadInitialPlaceholder = Boolean(input.getAttribute('placeholder'));
115
+ this.hadInitialPlaceholder = Boolean(input.getAttribute("placeholder"));
97
116
  }
98
117
 
99
118
  _init() {
100
119
  // if in nationalMode, do not insert dial codes
101
- if (this.options.nationalMode) this.options.autoInsertDialCode = false;
120
+ if (this.options.nationalMode) {
121
+ this.options.autoInsertDialCode = false;
122
+ }
102
123
 
103
124
  // if separateDialCode enabled, do not insert dial codes
104
- if (this.options.separateDialCode) this.options.autoInsertDialCode = false;
125
+ if (this.options.separateDialCode) {
126
+ this.options.autoInsertDialCode = false;
127
+ }
105
128
 
106
129
  // force showFlags=true if there's a dropdown and we're not displaying the dial code,
107
130
  // as otherwise you just have a down arrow on it's own which doesn't make sense
108
- const forceShowFlags = (this.options.allowDropdown && !this.options.separateDialCode);
131
+ const forceShowFlags =
132
+ this.options.allowDropdown && !this.options.separateDialCode;
109
133
  if (!this.options.showFlags && forceShowFlags) {
110
134
  this.options.showFlags = true;
111
135
  }
@@ -115,20 +139,25 @@ class Iti {
115
139
  // Note: for some reason jasmine breaks if you put this in the main Plugin function with the
116
140
  // rest of these declarations
117
141
  // Note: to target Android Mobiles (and not Tablets), we must find 'Android' and 'Mobile'
118
- this.isMobile = /Android.+Mobile|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
142
+ this.isMobile =
143
+ /Android.+Mobile|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
144
+ navigator.userAgent
145
+ );
119
146
 
120
147
  if (this.isMobile) {
121
148
  // trigger the mobile dropdown css
122
- document.body.classList.add('iti-mobile');
149
+ document.body.classList.add("iti-mobile");
123
150
 
124
151
  // on mobile, we want a full screen dropdown, so we must append it to the body
125
- if (!this.options.dropdownContainer) this.options.dropdownContainer = document.body;
152
+ if (!this.options.dropdownContainer) {
153
+ this.options.dropdownContainer = document.body;
154
+ }
126
155
  }
127
156
 
128
157
  // these promises get resolved when their individual requests complete
129
158
  // this way the dev can do something like iti.promise.then(...) to know when all requests are
130
159
  // complete
131
- if (typeof Promise !== 'undefined') {
160
+ if (typeof Promise !== "undefined") {
132
161
  const autoCountryPromise = new Promise((resolve, reject) => {
133
162
  this.resolveAutoCountryPromise = resolve;
134
163
  this.rejectAutoCountryPromise = reject;
@@ -164,12 +193,10 @@ class Iti {
164
193
  this._initRequests();
165
194
  }
166
195
 
167
-
168
196
  /********************
169
197
  * PRIVATE METHODS
170
198
  ********************/
171
199
 
172
-
173
200
  // prepare all of the country data, including onlyCountries, excludeCountries and
174
201
  // preferredCountries options
175
202
  _processCountryData() {
@@ -183,7 +210,9 @@ class Iti {
183
210
  this._processPreferredCountries();
184
211
 
185
212
  // translate countries according to localizedCountries option
186
- if (this.options.localizedCountries) this._translateCountriesByLocale();
213
+ if (this.options.localizedCountries) {
214
+ this._translateCountriesByLocale();
215
+ }
187
216
 
188
217
  // sort countries by name
189
218
  if (this.options.onlyCountries.length || this.options.localizedCountries) {
@@ -191,7 +220,6 @@ class Iti {
191
220
  }
192
221
  }
193
222
 
194
-
195
223
  // add a country code to this.countryCodes
196
224
  _addCountryCode(iso2, countryCode, priority) {
197
225
  if (countryCode.length > this.countryCodeMaxLen) {
@@ -202,29 +230,31 @@ class Iti {
202
230
  }
203
231
  // bail if we already have this country for this countryCode
204
232
  for (let i = 0; i < this.countryCodes[countryCode].length; i++) {
205
- if (this.countryCodes[countryCode][i] === iso2) return;
233
+ if (this.countryCodes[countryCode][i] === iso2) {
234
+ return;
235
+ }
206
236
  }
207
237
  // check for undefined as 0 is falsy
208
- const index = (priority !== undefined) ? priority : this.countryCodes[countryCode].length;
238
+ const index =
239
+ priority !== undefined ? priority : this.countryCodes[countryCode].length;
209
240
  this.countryCodes[countryCode][index] = iso2;
210
241
  }
211
242
 
212
-
213
243
  // process onlyCountries or excludeCountries array if present
214
244
  _processAllCountries() {
215
245
  if (this.options.onlyCountries.length) {
216
- const lowerCaseOnlyCountries = this.options.onlyCountries.map(
217
- country => country.toLowerCase()
246
+ const lowerCaseOnlyCountries = this.options.onlyCountries.map((country) =>
247
+ country.toLowerCase()
218
248
  );
219
249
  this.countries = allCountries.filter(
220
- country => lowerCaseOnlyCountries.indexOf(country.iso2) > -1
250
+ (country) => lowerCaseOnlyCountries.indexOf(country.iso2) > -1
221
251
  );
222
252
  } else if (this.options.excludeCountries.length) {
223
253
  const lowerCaseExcludeCountries = this.options.excludeCountries.map(
224
- country => country.toLowerCase()
254
+ (country) => country.toLowerCase()
225
255
  );
226
256
  this.countries = allCountries.filter(
227
- country => lowerCaseExcludeCountries.indexOf(country.iso2) === -1
257
+ (country) => lowerCaseExcludeCountries.indexOf(country.iso2) === -1
228
258
  );
229
259
  } else {
230
260
  this.countries = allCountries;
@@ -243,12 +273,15 @@ class Iti {
243
273
 
244
274
  // sort by country name
245
275
  _countryNameSort(a, b) {
246
- if (a.name < b.name) return -1;
247
- if (a.name > b.name) return 1;
276
+ if (a.name < b.name) {
277
+ return -1;
278
+ }
279
+ if (a.name > b.name) {
280
+ return 1;
281
+ }
248
282
  return 0;
249
283
  }
250
284
 
251
-
252
285
  // process the countryCodes map
253
286
  _processCountryCodes() {
254
287
  this.countryCodeMaxLen = 0;
@@ -260,7 +293,9 @@ class Iti {
260
293
  // first: add dial codes
261
294
  for (let i = 0; i < this.countries.length; i++) {
262
295
  const c = this.countries[i];
263
- if (!this.dialCodes[c.dialCode]) this.dialCodes[c.dialCode] = true;
296
+ if (!this.dialCodes[c.dialCode]) {
297
+ this.dialCodes[c.dialCode] = true;
298
+ }
264
299
  this._addCountryCode(c.iso2, c.dialCode, c.priority);
265
300
  }
266
301
 
@@ -290,7 +325,6 @@ class Iti {
290
325
  }
291
326
  }
292
327
 
293
-
294
328
  // process preferred countries - iterate through the preferences, fetching the country data for
295
329
  // each one
296
330
  _processPreferredCountries() {
@@ -298,28 +332,35 @@ class Iti {
298
332
  for (let i = 0; i < this.options.preferredCountries.length; i++) {
299
333
  const countryCode = this.options.preferredCountries[i].toLowerCase();
300
334
  const countryData = this._getCountryData(countryCode, false, true);
301
- if (countryData) this.preferredCountries.push(countryData);
335
+ if (countryData) {
336
+ this.preferredCountries.push(countryData);
337
+ }
302
338
  }
303
339
  }
304
340
 
305
-
306
341
  // create a DOM element
307
342
  _createEl(name, attrs, container) {
308
343
  const el = document.createElement(name);
309
- if (attrs) forEachProp(attrs, (key, value) => el.setAttribute(key, value));
310
- if (container) container.appendChild(el);
344
+ if (attrs) {
345
+ forEachProp(attrs, (key, value) => el.setAttribute(key, value));
346
+ }
347
+ if (container) {
348
+ container.appendChild(el);
349
+ }
311
350
  return el;
312
351
  }
313
352
 
314
-
315
353
  // generate all of the markup for the plugin: the selected flag overlay, and the dropdown
316
354
  _generateMarkup() {
317
355
  // if autocomplete does not exist on the element and its form, then
318
356
  // prevent autocomplete as there's no safe, cross-browser event we can react to, so it can
319
357
  // easily put the plugin in an inconsistent state e.g. the wrong flag selected for the
320
- // autocompleted number, which on submit could mean wrong number is saved (esp in nationalMode)
321
- if (!this.telInput.hasAttribute('autocomplete') && !(this.telInput.form && this.telInput.form.hasAttribute('autocomplete'))) {
322
- this.telInput.setAttribute('autocomplete', 'off');
358
+ // autocompleted number, which on submit could mean wrong number is saved
359
+ if (
360
+ !this.telInput.hasAttribute("autocomplete") &&
361
+ !(this.telInput.form && this.telInput.form.hasAttribute("autocomplete"))
362
+ ) {
363
+ this.telInput.setAttribute("autocomplete", "off");
323
364
  }
324
365
 
325
366
  const {
@@ -328,24 +369,34 @@ class Iti {
328
369
  showFlags,
329
370
  customContainer,
330
371
  hiddenInput,
331
- dropdownContainer,
372
+ dropdownContainer
332
373
  } = this.options;
333
374
 
334
375
  // containers (mostly for positioning)
335
- let parentClass = 'iti';
336
- if (allowDropdown) parentClass += ' iti--allow-dropdown';
337
- if (separateDialCode) parentClass += ' iti--separate-dial-code';
338
- if (showFlags) parentClass += ' iti--show-flags';
376
+ let parentClass = "iti";
377
+ if (allowDropdown) {
378
+ parentClass += " iti--allow-dropdown";
379
+ }
380
+ if (separateDialCode) {
381
+ parentClass += " iti--separate-dial-code";
382
+ }
383
+ if (showFlags) {
384
+ parentClass += " iti--show-flags";
385
+ }
339
386
  if (customContainer) {
340
387
  parentClass += ` ${customContainer}`;
341
388
  }
342
389
 
343
- const wrapper = this._createEl('div', { class: parentClass });
390
+ const wrapper = this._createEl("div", { class: parentClass });
344
391
  this.telInput.parentNode.insertBefore(wrapper, this.telInput);
345
392
  // only hide the flagsContainer if allowDropdown, showFlags and separateDialCode are all false
346
- const showFlagsContainer = (allowDropdown || showFlags || separateDialCode);
393
+ const showFlagsContainer = allowDropdown || showFlags || separateDialCode;
347
394
  if (showFlagsContainer) {
348
- this.flagsContainer = this._createEl('div', { class: 'iti__flag-container' }, wrapper);
395
+ this.flagsContainer = this._createEl(
396
+ "div",
397
+ { class: "iti__flag-container" },
398
+ wrapper
399
+ );
349
400
  }
350
401
  wrapper.appendChild(this.telInput);
351
402
 
@@ -353,58 +404,78 @@ class Iti {
353
404
  // using Aria tags for "Select-Only Combobox Example"
354
405
  // https://www.w3.org/WAI/ARIA/apg/patterns/combobox/examples/combobox-select-only/
355
406
  if (showFlagsContainer) {
356
- this.selectedFlag = this._createEl('div', {
357
- class: 'iti__selected-flag',
358
- ...(allowDropdown && {
359
- role: 'combobox',
360
- 'aria-haspopup': 'listbox',
361
- 'aria-controls': `iti-${this.id}__country-listbox`,
362
- 'aria-owns': `iti-${this.id}__country-listbox`,
363
- 'aria-expanded': 'false',
364
- 'aria-label': 'Telephone country code',
365
- }),
366
- }, this.flagsContainer);
407
+ this.selectedFlag = this._createEl(
408
+ "div",
409
+ {
410
+ class: "iti__selected-flag",
411
+ ...(allowDropdown && {
412
+ role: "combobox",
413
+ "aria-haspopup": "listbox",
414
+ "aria-controls": `iti-${this.id}__country-listbox`,
415
+ "aria-owns": `iti-${this.id}__country-listbox`,
416
+ "aria-expanded": "false",
417
+ "aria-label": "Telephone country code"
418
+ })
419
+ },
420
+ this.flagsContainer
421
+ );
367
422
  }
368
423
  if (showFlags) {
369
- this.selectedFlagInner = this._createEl('div', { class: 'iti__flag' }, this.selectedFlag);
424
+ this.selectedFlagInner = this._createEl(
425
+ "div",
426
+ { class: "iti__flag" },
427
+ this.selectedFlag
428
+ );
370
429
  }
371
430
 
372
431
  if (this.selectedFlag && this.telInput.disabled) {
373
- this.selectedFlag.setAttribute('aria-disabled', 'true');
432
+ this.selectedFlag.setAttribute("aria-disabled", "true");
374
433
  }
375
434
 
376
435
  if (separateDialCode) {
377
- this.selectedDialCode = this._createEl('div', { class: 'iti__selected-dial-code' }, this.selectedFlag);
436
+ this.selectedDialCode = this._createEl(
437
+ "div",
438
+ { class: "iti__selected-dial-code" },
439
+ this.selectedFlag
440
+ );
378
441
  }
379
442
 
380
443
  if (allowDropdown) {
381
444
  if (!this.telInput.disabled) {
382
445
  // make element focusable and tab navigable
383
- this.selectedFlag.setAttribute('tabindex', '0');
446
+ this.selectedFlag.setAttribute("tabindex", "0");
384
447
  }
385
448
 
386
- this.dropdownArrow = this._createEl('div', { class: 'iti__arrow' }, this.selectedFlag);
449
+ this.dropdownArrow = this._createEl(
450
+ "div",
451
+ { class: "iti__arrow" },
452
+ this.selectedFlag
453
+ );
387
454
 
388
455
  // country dropdown: preferred countries, then divider, then all countries
389
- this.countryList = this._createEl('ul', {
390
- class: 'iti__country-list iti__hide',
456
+ this.countryList = this._createEl("ul", {
457
+ class: "iti__country-list iti__hide",
391
458
  id: `iti-${this.id}__country-listbox`,
392
- role: 'listbox',
393
- 'aria-label': 'List of countries',
459
+ role: "listbox",
460
+ "aria-label": "List of countries"
394
461
  });
395
462
  if (this.preferredCountries.length) {
396
- this._appendListItems(this.preferredCountries, 'iti__preferred', true);
397
- this._createEl('li', {
398
- class: 'iti__divider',
399
- role: 'separator',
400
- 'aria-disabled': 'true',
401
- }, this.countryList);
463
+ this._appendListItems(this.preferredCountries, "iti__preferred", true);
464
+ this._createEl(
465
+ "li",
466
+ {
467
+ class: "iti__divider",
468
+ role: "separator",
469
+ "aria-disabled": "true"
470
+ },
471
+ this.countryList
472
+ );
402
473
  }
403
- this._appendListItems(this.countries, 'iti__standard');
474
+ this._appendListItems(this.countries, "iti__standard");
404
475
 
405
476
  // create dropdownContainer markup
406
477
  if (dropdownContainer) {
407
- this.dropdown = this._createEl('div', { class: 'iti iti--container' });
478
+ this.dropdown = this._createEl("div", { class: "iti iti--container" });
408
479
  this.dropdown.appendChild(this.countryList);
409
480
  } else {
410
481
  this.flagsContainer.appendChild(this.countryList);
@@ -413,31 +484,32 @@ class Iti {
413
484
 
414
485
  if (hiddenInput) {
415
486
  let hiddenInputName = hiddenInput;
416
- const name = this.telInput.getAttribute('name');
487
+ const name = this.telInput.getAttribute("name");
417
488
  if (name) {
418
- const i = name.lastIndexOf('[');
489
+ const i = name.lastIndexOf("[");
419
490
  // if input name contains square brackets, then give the hidden input the same name,
420
491
  // replacing the contents of the last set of brackets with the given hiddenInput name
421
- if (i !== -1) hiddenInputName = `${name.substr(0, i)}[${hiddenInputName}]`;
492
+ if (i !== -1) {
493
+ hiddenInputName = `${name.substr(0, i)}[${hiddenInputName}]`;
494
+ }
422
495
  }
423
- this.hiddenInput = this._createEl('input', {
424
- type: 'hidden',
425
- name: hiddenInputName,
496
+ this.hiddenInput = this._createEl("input", {
497
+ type: "hidden",
498
+ name: hiddenInputName
426
499
  });
427
500
  wrapper.appendChild(this.hiddenInput);
428
501
  }
429
502
  }
430
503
 
431
-
432
504
  // add a country <li> to the countryList <ul> container
433
505
  _appendListItems(countries, className, preferred) {
434
506
  // we create so many DOM elements, it is faster to build a temp string
435
507
  // and then add everything to the DOM in one go at the end
436
- let tmp = '';
508
+ let tmp = "";
437
509
  // for each country
438
510
  for (let i = 0; i < countries.length; i++) {
439
511
  const c = countries[i];
440
- const idSuffix = preferred ? '-preferred' : '';
512
+ const idSuffix = preferred ? "-preferred" : "";
441
513
  // open the list item
442
514
  tmp += `<li class='iti__country ${className}' tabIndex='-1' id='iti-${this.id}__item-${c.iso2}${idSuffix}' role='option' data-dial-code='${c.dialCode}' data-country-code='${c.iso2}' aria-selected='false'>`;
443
515
  // add the flag
@@ -448,12 +520,11 @@ class Iti {
448
520
  tmp += `<span class='iti__country-name'>${c.name}</span>`;
449
521
  tmp += `<span class='iti__dial-code'>+${c.dialCode}</span>`;
450
522
  // close the list item
451
- tmp += '</li>';
523
+ tmp += "</li>";
452
524
  }
453
- this.countryList.insertAdjacentHTML('beforeend', tmp);
525
+ this.countryList.insertAdjacentHTML("beforeend", tmp);
454
526
  }
455
527
 
456
-
457
528
  // set the initial state of the input value and the selected flag by:
458
529
  // 1. extracting a dial code from the given number
459
530
  // 2. using explicit initialCountry
@@ -463,32 +534,33 @@ class Iti {
463
534
  // fix firefox bug: when first load page (with input with value set to number with intl dial
464
535
  // code) and initialising plugin removes the dial code from the input, then refresh page,
465
536
  // and we try to init plugin again but this time on number without dial code so get grey flag
466
- const attributeValue = this.telInput.getAttribute('value');
537
+ const attributeValue = this.telInput.getAttribute("value");
467
538
  const inputValue = this.telInput.value;
468
- const useAttribute = (attributeValue && attributeValue.charAt(0) === '+' && (!inputValue || inputValue.charAt(0) !== '+'));
539
+ const useAttribute =
540
+ attributeValue &&
541
+ attributeValue.charAt(0) === "+" &&
542
+ (!inputValue || inputValue.charAt(0) !== "+");
469
543
  const val = useAttribute ? attributeValue : inputValue;
470
544
  const dialCode = this._getDialCode(val);
471
545
  const isRegionlessNanp = this._isRegionlessNanp(val);
472
- const {
473
- initialCountry,
474
- autoInsertDialCode,
475
- } = this.options;
546
+ const { initialCountry, autoInsertDialCode } = this.options;
476
547
 
477
548
  // if we already have a dial code, and it's not a regionlessNanp, we can go ahead and set the
478
549
  // flag, else fall back to the default country
479
550
  if (dialCode && !isRegionlessNanp) {
480
551
  this._updateFlagFromNumber(val);
481
- } else if (initialCountry !== 'auto') {
552
+ } else if (initialCountry !== "auto") {
482
553
  // see if we should select a flag
483
554
  if (initialCountry) {
484
555
  this._setFlag(initialCountry.toLowerCase());
485
556
  } else {
486
557
  if (dialCode && isRegionlessNanp) {
487
558
  // has intl dial code, is regionless nanp, and no initialCountry, so default to US
488
- this._setFlag('us');
559
+ this._setFlag("us");
489
560
  } else {
490
561
  // no dial code and no initialCountry, so default to first in list
491
- this.defaultCountry = (this.preferredCountries.length) ? this.preferredCountries[0].iso2
562
+ this.defaultCountry = this.preferredCountries.length
563
+ ? this.preferredCountries[0].iso2
492
564
  : this.countries[0].iso2;
493
565
  if (!val) {
494
566
  this._setFlag(this.defaultCountry);
@@ -504,36 +576,47 @@ class Iti {
504
576
  // NOTE: if initialCountry is set to auto, that will be handled separately
505
577
 
506
578
  // format - note this wont be run after _updateDialCode as that's only called if no val
507
- if (val) this._updateValFromNumber(val);
579
+ if (val) {
580
+ this._updateValFromNumber(val);
581
+ }
508
582
  }
509
583
 
510
-
511
584
  // initialise the main event listeners: input keyup, and click selected flag
512
585
  _initListeners() {
513
586
  this._initKeyListeners();
514
- if (this.options.autoInsertDialCode) this._initBlurListeners();
515
- if (this.options.allowDropdown) this._initDropdownListeners();
516
- if (this.hiddenInput) this._initHiddenInputListener();
587
+ if (this.options.autoInsertDialCode) {
588
+ this._initBlurListeners();
589
+ }
590
+ if (this.options.allowDropdown) {
591
+ this._initDropdownListeners();
592
+ }
593
+ if (this.hiddenInput) {
594
+ this._initHiddenInputListener();
595
+ }
517
596
  }
518
597
 
519
-
520
598
  // update hidden input on form submit
521
599
  _initHiddenInputListener() {
522
600
  this._handleHiddenInputSubmit = () => {
523
601
  this.hiddenInput.value = this.getNumber();
524
602
  };
525
- if (this.telInput.form) this.telInput.form.addEventListener('submit', this._handleHiddenInputSubmit);
603
+ if (this.telInput.form) {
604
+ this.telInput.form.addEventListener(
605
+ "submit",
606
+ this._handleHiddenInputSubmit
607
+ );
608
+ }
526
609
  }
527
610
 
528
-
529
611
  // iterate through parent nodes to find the closest label ancestor, if it exists
530
612
  _getClosestLabel() {
531
613
  let el = this.telInput;
532
- while (el && el.tagName !== 'LABEL') el = el.parentNode;
614
+ while (el && el.tagName !== "LABEL") {
615
+ el = el.parentNode;
616
+ }
533
617
  return el;
534
618
  }
535
619
 
536
-
537
620
  // initialise the dropdown listeners
538
621
  _initDropdownListeners() {
539
622
  // hack for input nested inside label (which is valid markup): clicking the selected-flag to
@@ -541,28 +624,41 @@ class Iti {
541
624
  // close it again
542
625
  this._handleLabelClick = (e) => {
543
626
  // if the dropdown is closed, then focus the input, else ignore the click
544
- if (this.countryList.classList.contains('iti__hide')) this.telInput.focus();
545
- else e.preventDefault();
627
+ if (this.countryList.classList.contains("iti__hide")) {
628
+ this.telInput.focus();
629
+ } else {
630
+ e.preventDefault();
631
+ }
546
632
  };
547
633
  const label = this._getClosestLabel();
548
- if (label) label.addEventListener('click', this._handleLabelClick);
634
+ if (label) {
635
+ label.addEventListener("click", this._handleLabelClick);
636
+ }
549
637
 
550
638
  // toggle country dropdown on click
551
639
  this._handleClickSelectedFlag = () => {
552
640
  // only intercept this event if we're opening the dropdown
553
641
  // else let it bubble up to the top ("click-off-to-close" listener)
554
642
  // we cannot just stopPropagation as it may be needed to close another instance
555
- if (this.countryList.classList.contains('iti__hide') && !this.telInput.disabled && !this.telInput.readOnly) {
643
+ if (
644
+ this.countryList.classList.contains("iti__hide") &&
645
+ !this.telInput.disabled &&
646
+ !this.telInput.readOnly
647
+ ) {
556
648
  this._showDropdown();
557
649
  }
558
650
  };
559
- this.selectedFlag.addEventListener('click', this._handleClickSelectedFlag);
651
+ this.selectedFlag.addEventListener("click", this._handleClickSelectedFlag);
560
652
 
561
653
  // open dropdown list if currently focused
562
654
  this._handleFlagsContainerKeydown = (e) => {
563
- const isDropdownHidden = this.countryList.classList.contains('iti__hide');
655
+ const isDropdownHidden = this.countryList.classList.contains("iti__hide");
564
656
 
565
- if (isDropdownHidden && ['ArrowUp', 'Up', 'ArrowDown', 'Down', ' ', 'Enter'].indexOf(e.key) !== -1) {
657
+ if (
658
+ isDropdownHidden &&
659
+ ["ArrowUp", "Up", "ArrowDown", "Down", " ", "Enter"].indexOf(e.key) !==
660
+ -1
661
+ ) {
566
662
  // prevent form from being submitted if "ENTER" was pressed
567
663
  e.preventDefault();
568
664
  // prevent event from being handled again by document
@@ -571,12 +667,16 @@ class Iti {
571
667
  }
572
668
 
573
669
  // allow navigation from dropdown to input on TAB
574
- if (e.key === 'Tab') this._closeDropdown();
670
+ if (e.key === "Tab") {
671
+ this._closeDropdown();
672
+ }
575
673
  };
576
- this.flagsContainer.addEventListener('keydown', this._handleFlagsContainerKeydown);
674
+ this.flagsContainer.addEventListener(
675
+ "keydown",
676
+ this._handleFlagsContainerKeydown
677
+ );
577
678
  }
578
679
 
579
-
580
680
  // init many requests: utils script / geo ip lookup
581
681
  _initRequests() {
582
682
  // if the user has specified the path to the utils script, fetch it on window.load, else resolve
@@ -586,17 +686,21 @@ class Iti {
586
686
  window.intlTelInputGlobals.loadUtils(this.options.utilsScript);
587
687
  } else {
588
688
  // wait until the load event so we don't block any other requests e.g. the flags image
589
- window.addEventListener('load', () => {
689
+ window.addEventListener("load", () => {
590
690
  window.intlTelInputGlobals.loadUtils(this.options.utilsScript);
591
691
  });
592
692
  }
593
- } else this.resolveUtilsScriptPromise();
693
+ } else {
694
+ this.resolveUtilsScriptPromise();
695
+ }
594
696
 
595
- if (this.options.initialCountry === 'auto') this._loadAutoCountry();
596
- else this.resolveAutoCountryPromise();
697
+ if (this.options.initialCountry === "auto") {
698
+ this._loadAutoCountry();
699
+ } else {
700
+ this.resolveAutoCountryPromise();
701
+ }
597
702
  }
598
703
 
599
-
600
704
  // perform the geo ip lookup
601
705
  _loadAutoCountry() {
602
706
  // 3 options:
@@ -609,22 +713,24 @@ class Iti {
609
713
  // don't do this twice!
610
714
  window.intlTelInputGlobals.startedLoadingAutoCountry = true;
611
715
 
612
- if (typeof this.options.geoIpLookup === 'function') {
613
- this.options.geoIpLookup((countryCode) => {
614
- window.intlTelInputGlobals.autoCountry = countryCode.toLowerCase();
615
- // tell all instances the auto country is ready
616
- // TODO: this should just be the current instances
617
- // UPDATE: use setTimeout in case their geoIpLookup function calls this callback straight
618
- // away (e.g. if they have already done the geo ip lookup somewhere else). Using
619
- // setTimeout means that the current thread of execution will finish before executing
620
- // this, which allows the plugin to finish initialising.
621
- setTimeout(() => forEachInstance('handleAutoCountry'));
622
- }, () => forEachInstance('rejectAutoCountryPromise'));
716
+ if (typeof this.options.geoIpLookup === "function") {
717
+ this.options.geoIpLookup(
718
+ (countryCode) => {
719
+ window.intlTelInputGlobals.autoCountry = countryCode.toLowerCase();
720
+ // tell all instances the auto country is ready
721
+ // TODO: this should just be the current instances
722
+ // UPDATE: use setTimeout in case their geoIpLookup function calls this callback straight
723
+ // away (e.g. if they have already done the geo ip lookup somewhere else). Using
724
+ // setTimeout means that the current thread of execution will finish before executing
725
+ // this, which allows the plugin to finish initialising.
726
+ setTimeout(() => forEachInstance("handleAutoCountry"));
727
+ },
728
+ () => forEachInstance("rejectAutoCountryPromise")
729
+ );
623
730
  }
624
731
  }
625
732
  }
626
733
 
627
-
628
734
  // initialize any key listeners
629
735
  _initKeyListeners() {
630
736
  // update flag on keyup
@@ -633,71 +739,70 @@ class Iti {
633
739
  this._triggerCountryChange();
634
740
  }
635
741
  };
636
- this.telInput.addEventListener('keyup', this._handleKeyupEvent);
742
+ this.telInput.addEventListener("keyup", this._handleKeyupEvent);
637
743
 
638
744
  // update flag on cut/paste events (now supported in all major browsers)
639
745
  this._handleClipboardEvent = () => {
640
746
  // hack because "paste" event is fired before input is updated
641
747
  setTimeout(this._handleKeyupEvent);
642
748
  };
643
- this.telInput.addEventListener('cut', this._handleClipboardEvent);
644
- this.telInput.addEventListener('paste', this._handleClipboardEvent);
749
+ this.telInput.addEventListener("cut", this._handleClipboardEvent);
750
+ this.telInput.addEventListener("paste", this._handleClipboardEvent);
645
751
  }
646
752
 
647
-
648
753
  // adhere to the input's maxlength attr
649
754
  _cap(number) {
650
- const max = this.telInput.getAttribute('maxlength');
651
- return (max && number.length > max) ? number.substr(0, max) : number;
755
+ const max = this.telInput.getAttribute("maxlength");
756
+ return max && number.length > max ? number.substr(0, max) : number;
652
757
  }
653
758
 
654
-
655
759
  // listen for blur/submit (for autoInsertDialCode feature)
656
760
  _initBlurListeners() {
657
761
  // on blur or form submit: if just a dial code then remove it
658
762
  this._handleSubmitOrBlurEvent = () => {
659
763
  this._removeEmptyDialCode();
660
764
  };
661
- if (this.telInput.form) this.telInput.form.addEventListener('submit', this._handleSubmitOrBlurEvent);
662
- this.telInput.addEventListener('blur', this._handleSubmitOrBlurEvent);
765
+ if (this.telInput.form) {
766
+ this.telInput.form.addEventListener(
767
+ "submit",
768
+ this._handleSubmitOrBlurEvent
769
+ );
770
+ }
771
+ this.telInput.addEventListener("blur", this._handleSubmitOrBlurEvent);
663
772
 
664
773
  // made the decision not to trigger blur() now, because would only do anything in the case
665
774
  // where they manually set the initial value to just a dial code, in which case they probably
666
775
  // want it to be displayed.
667
776
  }
668
777
 
669
-
670
778
  // clear the input if it just contains a dial code
671
779
  _removeEmptyDialCode() {
672
- if (this.telInput.value.charAt(0) === '+') {
780
+ if (this.telInput.value.charAt(0) === "+") {
673
781
  const numeric = this._getNumeric(this.telInput.value);
674
782
  // if just a plus, or if just a dial code
675
783
  if (!numeric || this.selectedCountryData.dialCode === numeric) {
676
- this.telInput.value = '';
784
+ this.telInput.value = "";
677
785
  }
678
786
  }
679
787
  }
680
788
 
681
-
682
789
  // extract the numeric digits from the given string
683
790
  _getNumeric(s) {
684
- return s.replace(/\D/g, '');
791
+ return s.replace(/\D/g, "");
685
792
  }
686
793
 
687
-
688
794
  // trigger a custom event on the input
689
795
  _trigger(name) {
690
796
  // have to use old school document.createEvent as IE11 doesn't support `new Event()` syntax
691
- const e = document.createEvent('Event');
797
+ const e = document.createEvent("Event");
692
798
  e.initEvent(name, true, true); // can bubble, and is cancellable
693
799
  this.telInput.dispatchEvent(e);
694
800
  }
695
801
 
696
-
697
802
  // show the dropdown
698
803
  _showDropdown() {
699
- this.countryList.classList.remove('iti__hide');
700
- this.selectedFlag.setAttribute('aria-expanded', 'true');
804
+ this.countryList.classList.remove("iti__hide");
805
+ this.selectedFlag.setAttribute("aria-expanded", "true");
701
806
 
702
807
  this._setDropdownPosition();
703
808
 
@@ -711,19 +816,20 @@ class Iti {
711
816
  this._bindDropdownListeners();
712
817
 
713
818
  // update the arrow
714
- this.dropdownArrow.classList.add('iti__arrow--up');
819
+ this.dropdownArrow.classList.add("iti__arrow--up");
715
820
 
716
- this._trigger('open:countrydropdown');
821
+ this._trigger("open:countrydropdown");
717
822
  }
718
823
 
719
-
720
824
  // make sure the el has the className or not, depending on the value of shouldHaveClass
721
825
  _toggleClass(el, className, shouldHaveClass) {
722
- if (shouldHaveClass && !el.classList.contains(className)) el.classList.add(className);
723
- else if (!shouldHaveClass && el.classList.contains(className)) el.classList.remove(className);
826
+ if (shouldHaveClass && !el.classList.contains(className)) {
827
+ el.classList.add(className);
828
+ } else if (!shouldHaveClass && el.classList.contains(className)) {
829
+ el.classList.remove(className);
830
+ }
724
831
  }
725
832
 
726
-
727
833
  // decide where to position dropdown (depends on position within viewport, and scroll)
728
834
  _setDropdownPosition() {
729
835
  if (this.options.dropdownContainer) {
@@ -733,23 +839,32 @@ class Iti {
733
839
  if (!this.isMobile) {
734
840
  const pos = this.telInput.getBoundingClientRect();
735
841
  // windowTop from https://stackoverflow.com/a/14384091/217866
736
- const windowTop = window.pageYOffset || document.documentElement.scrollTop;
842
+ const windowTop =
843
+ window.pageYOffset || document.documentElement.scrollTop;
737
844
  const inputTop = pos.top + windowTop;
738
845
  const dropdownHeight = this.countryList.offsetHeight;
739
846
  // dropdownFitsBelow = (dropdownBottom < windowBottom)
740
- const dropdownFitsBelow = (inputTop + this.telInput.offsetHeight + dropdownHeight
741
- < (windowTop + window.innerHeight));
742
- const dropdownFitsAbove = (inputTop - dropdownHeight > windowTop);
847
+ const dropdownFitsBelow =
848
+ inputTop + this.telInput.offsetHeight + dropdownHeight <
849
+ windowTop + window.innerHeight;
850
+ const dropdownFitsAbove = inputTop - dropdownHeight > windowTop;
743
851
 
744
852
  // by default, the dropdown will be below the input. If we want to position it above the
745
853
  // input, we add the dropup class.
746
- this._toggleClass(this.countryList, 'iti__country-list--dropup', (!dropdownFitsBelow && dropdownFitsAbove));
854
+ this._toggleClass(
855
+ this.countryList,
856
+ "iti__country-list--dropup",
857
+ !dropdownFitsBelow && dropdownFitsAbove
858
+ );
747
859
 
748
860
  // if dropdownContainer is enabled, calculate postion
749
861
  if (this.options.dropdownContainer) {
750
862
  // by default the dropdown will be directly over the input because it's not in the flow.
751
863
  // If we want to position it below, we need to add some extra top value.
752
- const extraTop = (!dropdownFitsBelow && dropdownFitsAbove) ? 0 : this.telInput.offsetHeight;
864
+ const extraTop =
865
+ !dropdownFitsBelow && dropdownFitsAbove
866
+ ? 0
867
+ : this.telInput.offsetHeight;
753
868
 
754
869
  // calculate placement
755
870
  this.dropdown.style.top = `${inputTop + extraTop}px`;
@@ -757,21 +872,25 @@ class Iti {
757
872
 
758
873
  // close menu on window scroll
759
874
  this._handleWindowScroll = () => this._closeDropdown();
760
- window.addEventListener('scroll', this._handleWindowScroll);
875
+ window.addEventListener("scroll", this._handleWindowScroll);
761
876
  }
762
877
  }
763
878
  }
764
879
 
765
-
766
880
  // iterate through parent nodes to find the closest list item
767
881
  _getClosestListItem(target) {
768
882
  let el = target;
769
- while (el && el !== this.countryList && !el.classList.contains('iti__country')) el = el.parentNode;
883
+ while (
884
+ el &&
885
+ el !== this.countryList &&
886
+ !el.classList.contains("iti__country")
887
+ ) {
888
+ el = el.parentNode;
889
+ }
770
890
  // if we reached the countryList element, then return null
771
- return (el === this.countryList) ? null : el;
891
+ return el === this.countryList ? null : el;
772
892
  }
773
893
 
774
-
775
894
  // we only bind dropdown listeners when the dropdown is open
776
895
  _bindDropdownListeners() {
777
896
  // when mouse over a list item, just highlight that one
@@ -779,32 +898,44 @@ class Iti {
779
898
  this._handleMouseoverCountryList = (e) => {
780
899
  // handle event delegation, as we're listening for this event on the countryList
781
900
  const listItem = this._getClosestListItem(e.target);
782
- if (listItem) this._highlightListItem(listItem, false);
901
+ if (listItem) {
902
+ this._highlightListItem(listItem, false);
903
+ }
783
904
  };
784
- this.countryList.addEventListener('mouseover', this._handleMouseoverCountryList);
905
+ this.countryList.addEventListener(
906
+ "mouseover",
907
+ this._handleMouseoverCountryList
908
+ );
785
909
 
786
910
  // listen for country selection
787
911
  this._handleClickCountryList = (e) => {
788
912
  const listItem = this._getClosestListItem(e.target);
789
- if (listItem) this._selectListItem(listItem);
913
+ if (listItem) {
914
+ this._selectListItem(listItem);
915
+ }
790
916
  };
791
- this.countryList.addEventListener('click', this._handleClickCountryList);
917
+ this.countryList.addEventListener("click", this._handleClickCountryList);
792
918
 
793
919
  // click off to close
794
920
  // (except when this initial opening click is bubbling up)
795
921
  // we cannot just stopPropagation as it may be needed to close another instance
796
922
  let isOpening = true;
797
923
  this._handleClickOffToClose = () => {
798
- if (!isOpening) this._closeDropdown();
924
+ if (!isOpening) {
925
+ this._closeDropdown();
926
+ }
799
927
  isOpening = false;
800
928
  };
801
- document.documentElement.addEventListener('click', this._handleClickOffToClose);
929
+ document.documentElement.addEventListener(
930
+ "click",
931
+ this._handleClickOffToClose
932
+ );
802
933
 
803
934
  // listen for up/down scrolling, enter to select, or letters to jump to country name.
804
935
  // use keydown as keypress doesn't fire for non-char keys and we want to catch if they
805
936
  // just hit down and hold it to scroll down (no keyup event).
806
937
  // listen on the document because that's where key events are triggered if no input has focus
807
- let query = '';
938
+ let query = "";
808
939
  let queryTimer = null;
809
940
  this._handleKeydownOnDropdown = (e) => {
810
941
  // prevent down key from scrolling the whole page,
@@ -812,52 +943,72 @@ class Iti {
812
943
  e.preventDefault();
813
944
 
814
945
  // up and down to navigate
815
- if (e.key === 'ArrowUp' || e.key === 'Up' || e.key === 'ArrowDown' || e.key === 'Down') this._handleUpDownKey(e.key);
946
+ if (
947
+ e.key === "ArrowUp" ||
948
+ e.key === "Up" ||
949
+ e.key === "ArrowDown" ||
950
+ e.key === "Down"
951
+ ) {
952
+ this._handleUpDownKey(e.key);
953
+ }
816
954
  // enter to select
817
- else if (e.key === 'Enter') this._handleEnterKey();
955
+ else if (e.key === "Enter") {
956
+ this._handleEnterKey();
957
+ }
818
958
  // esc to close
819
- else if (e.key === 'Escape') this._closeDropdown();
959
+ else if (e.key === "Escape") {
960
+ this._closeDropdown();
961
+ }
820
962
  // alpha chars to perform search
821
963
  // regex allows one latin alpha char or space, based on https://stackoverflow.com/a/26900132/217866)
822
964
  else if (/^[a-zA-ZÀ-ÿа-яА-Я ]$/.test(e.key)) {
823
965
  // jump to countries that start with the query string
824
- if (queryTimer) clearTimeout(queryTimer);
966
+ if (queryTimer) {
967
+ clearTimeout(queryTimer);
968
+ }
825
969
  query += e.key.toLowerCase();
826
970
  this._searchForCountry(query);
827
971
  // if the timer hits 1 second, reset the query
828
972
  queryTimer = setTimeout(() => {
829
- query = '';
973
+ query = "";
830
974
  }, 1000);
831
975
  }
832
976
  };
833
- document.addEventListener('keydown', this._handleKeydownOnDropdown);
977
+ document.addEventListener("keydown", this._handleKeydownOnDropdown);
834
978
  }
835
979
 
836
-
837
980
  // highlight the next/prev item in the list (and ensure it is visible)
838
981
  _handleUpDownKey(key) {
839
- let next = (key === 'ArrowUp' || key === 'Up') ? this.highlightedItem.previousElementSibling : this.highlightedItem.nextElementSibling;
982
+ let next =
983
+ key === "ArrowUp" || key === "Up"
984
+ ? this.highlightedItem.previousElementSibling
985
+ : this.highlightedItem.nextElementSibling;
840
986
  if (next) {
841
987
  // skip the divider
842
- if (next.classList.contains('iti__divider')) {
843
- next = (key === 'ArrowUp' || key === 'Up') ? next.previousElementSibling : next.nextElementSibling;
988
+ if (next.classList.contains("iti__divider")) {
989
+ next =
990
+ key === "ArrowUp" || key === "Up"
991
+ ? next.previousElementSibling
992
+ : next.nextElementSibling;
844
993
  }
845
994
  this._highlightListItem(next, true);
846
995
  }
847
996
  }
848
997
 
849
-
850
998
  // select the currently highlighted item
851
999
  _handleEnterKey() {
852
- if (this.highlightedItem) this._selectListItem(this.highlightedItem);
1000
+ if (this.highlightedItem) {
1001
+ this._selectListItem(this.highlightedItem);
1002
+ }
853
1003
  }
854
1004
 
855
-
856
1005
  // find the first list item whose name starts with the query string
857
1006
  _searchForCountry(query) {
858
1007
  for (let i = 0; i < this.countries.length; i++) {
859
1008
  if (this._startsWith(this.countries[i].name, query)) {
860
- const listItem = this.countryList.querySelector(`#iti-${this.id}__item-${this.countries[i].iso2}`);
1009
+ const listItem = this.countryList.querySelector(
1010
+ `#iti-${this.id}__item-${this.countries[i].iso2}`
1011
+ );
861
1012
  // update highlighting and scroll
862
1013
  this._highlightListItem(listItem, false);
863
1014
  this._scrollTo(listItem, true);
@@ -866,47 +1017,60 @@ class Iti {
866
1017
  }
867
1018
  }
868
1019
 
869
-
870
1020
  // check if string a starts with string b
871
1021
  _startsWith(a, b) {
872
- return (a.substr(0, b.length).toLowerCase() === b);
1022
+ return a.substr(0, b.length).toLowerCase() === b;
873
1023
  }
874
1024
 
875
-
876
1025
  // update the input's value to the given val (format first if possible)
877
1026
  // NOTE: this is called from _setInitialState, handleUtils and setNumber
878
1027
  _updateValFromNumber(originalNumber) {
879
1028
  let number = originalNumber;
880
- if (this.options.formatOnDisplay && window.intlTelInputUtils && this.selectedCountryData) {
881
- const useNational = (this.options.nationalMode || (number.charAt(0) !== '+' && !this.options.separateDialCode));
1029
+ if (
1030
+ this.options.formatOnDisplay &&
1031
+ window.intlTelInputUtils &&
1032
+ this.selectedCountryData
1033
+ ) {
1034
+ const useNational =
1035
+ this.options.nationalMode ||
1036
+ (number.charAt(0) !== "+" && !this.options.separateDialCode);
882
1037
  const { NATIONAL, INTERNATIONAL } = intlTelInputUtils.numberFormat;
883
1038
  const format = useNational ? NATIONAL : INTERNATIONAL;
884
- number = intlTelInputUtils.formatNumber(number, this.selectedCountryData.iso2, format);
1039
+ number = intlTelInputUtils.formatNumber(
1040
+ number,
1041
+ this.selectedCountryData.iso2,
1042
+ format
1043
+ );
885
1044
  }
886
1045
 
887
1046
  number = this._beforeSetNumber(number);
888
1047
  this.telInput.value = number;
889
1048
  }
890
1049
 
891
-
892
1050
  // check if need to select a new flag based on the given number
893
1051
  // Note: called from _setInitialState, keyup handler, setNumber
894
1052
  _updateFlagFromNumber(originalNumber) {
895
- // if we're in nationalMode and we already have US/Canada selected, make sure the number starts
1053
+ // if we already have US/Canada selected, make sure the number starts
896
1054
  // with a +1 so _getDialCode will be able to extract the area code
897
1055
  // update: if we dont yet have selectedCountryData, but we're here (trying to update the flag
898
1056
  // from the number), that means we're initialising the plugin with a number that already has a
899
1057
  // dial code, so fine to ignore this bit
900
1058
  let number = originalNumber;
901
1059
  const selectedDialCode = this.selectedCountryData.dialCode;
902
- const isNanp = (selectedDialCode === '1');
903
- if (number && this.options.nationalMode && isNanp && number.charAt(0) !== '+') {
904
- if (number.charAt(0) !== '1') number = `1${number}`;
1060
+ const isNanp = selectedDialCode === "1";
1061
+ if (number && isNanp && number.charAt(0) !== "+") {
1062
+ if (number.charAt(0) !== "1") {
1063
+ number = `1${number}`;
1064
+ }
905
1065
  number = `+${number}`;
906
1066
  }
907
1067
 
908
1068
  // if separateDialCode enabled, then consider the selected dial code to be part of the number
909
- if (this.options.separateDialCode && selectedDialCode && number.charAt(0) !== '+') {
1069
+ if (
1070
+ this.options.separateDialCode &&
1071
+ selectedDialCode &&
1072
+ number.charAt(0) !== "+"
1073
+ ) {
910
1074
  number = `+${selectedDialCode}${number}`;
911
1075
  }
912
1076
 
@@ -920,9 +1084,11 @@ class Iti {
920
1084
  // longer than the matched dial code because in this case we need to make sure that if
921
1085
  // there are multiple country matches, that the first one is selected (note: we could
922
1086
  // just check that here, but it requires the same loop that we already have later)
923
- const alreadySelected = (countryCodes.indexOf(this.selectedCountryData.iso2) !== -1)
924
- && (numeric.length <= dialCode.length - 1);
925
- const isRegionlessNanpNumber = (selectedDialCode === '1' && this._isRegionlessNanp(numeric));
1087
+ const alreadySelected =
1088
+ countryCodes.indexOf(this.selectedCountryData.iso2) !== -1 &&
1089
+ numeric.length <= dialCode.length - 1;
1090
+ const isRegionlessNanpNumber =
1091
+ selectedDialCode === "1" && this._isRegionlessNanp(numeric);
926
1092
 
927
1093
  // only update the flag if:
928
1094
  // A) NOT (we currently have a NANP flag selected, and the number is a regionlessNanp)
@@ -938,12 +1104,12 @@ class Iti {
938
1104
  }
939
1105
  }
940
1106
  }
941
- } else if (number.charAt(0) === '+' && numeric.length) {
1107
+ } else if (number.charAt(0) === "+" && numeric.length) {
942
1108
  // invalid dial code, so empty
943
1109
  // Note: use getNumeric here because the number has not been formatted yet, so could contain
944
1110
  // bad chars
945
- countryCode = '';
946
- } else if (!number || number === '+') {
1111
+ countryCode = "";
1112
+ } else if (!number || number === "+") {
947
1113
  // empty, or just a plus, so default
948
1114
  countryCode = this.defaultCountry;
949
1115
  }
@@ -954,35 +1120,41 @@ class Iti {
954
1120
  return false;
955
1121
  }
956
1122
 
957
-
958
1123
  // check if the given number is a regionless NANP number (expects the number to contain an
959
1124
  // international dial code)
960
1125
  _isRegionlessNanp(number) {
961
1126
  const numeric = this._getNumeric(number);
962
- if (numeric.charAt(0) === '1') {
1127
+ if (numeric.charAt(0) === "1") {
963
1128
  const areaCode = numeric.substr(1, 3);
964
- return (regionlessNanpNumbers.indexOf(areaCode) !== -1);
1129
+ return regionlessNanpNumbers.indexOf(areaCode) !== -1;
965
1130
  }
966
1131
  return false;
967
1132
  }
968
1133
 
969
-
970
1134
  // remove highlighting from other list items and highlight the given item
971
1135
  _highlightListItem(listItem, shouldFocus) {
972
1136
  const prevItem = this.highlightedItem;
973
- if (prevItem) prevItem.classList.remove('iti__highlight');
1137
+ if (prevItem) {
1138
+ prevItem.classList.remove("iti__highlight");
1139
+ }
974
1140
  this.highlightedItem = listItem;
975
- this.highlightedItem.classList.add('iti__highlight');
976
- this.selectedFlag.setAttribute('aria-activedescendant', listItem.getAttribute('id'));
977
-
978
- if (shouldFocus) this.highlightedItem.focus();
1141
+ this.highlightedItem.classList.add("iti__highlight");
1142
+ this.selectedFlag.setAttribute(
1143
+ "aria-activedescendant",
1144
+ listItem.getAttribute("id")
1145
+ );
1146
+
1147
+ if (shouldFocus) {
1148
+ this.highlightedItem.focus();
1149
+ }
979
1150
  }
980
1151
 
981
-
982
1152
  // find the country data for the given country code
983
1153
  // the ignoreOnlyCountriesOption is only used during init() while parsing the onlyCountries array
984
1154
  _getCountryData(countryCode, ignoreOnlyCountriesOption, allowFail) {
985
- const countryList = (ignoreOnlyCountriesOption) ? allCountries : this.countries;
1155
+ const countryList = ignoreOnlyCountriesOption
1156
+ ? allCountries
1157
+ : this.countries;
986
1158
  for (let i = 0; i < countryList.length; i++) {
987
1159
  if (countryList[i].iso2 === countryCode) {
988
1160
  return countryList[i];
@@ -994,33 +1166,44 @@ class Iti {
994
1166
  throw new Error(`No country data for '${countryCode}'`);
995
1167
  }
996
1168
 
997
-
998
1169
  // select the given flag, update the placeholder and the active list item
999
1170
  // Note: called from _setInitialState, _updateFlagFromNumber, _selectListItem, setCountry
1000
1171
  _setFlag(countryCode) {
1001
- const prevCountry = (this.selectedCountryData.iso2) ? this.selectedCountryData : {};
1172
+ const prevCountry = this.selectedCountryData.iso2
1173
+ ? this.selectedCountryData
1174
+ : {};
1002
1175
 
1003
1176
  // do this first as it will throw an error and stop if countryCode is invalid
1004
- this.selectedCountryData = (countryCode) ? this._getCountryData(countryCode, false, false) : {};
1177
+ this.selectedCountryData = countryCode
1178
+ ? this._getCountryData(countryCode, false, false)
1179
+ : {};
1005
1180
  // update the defaultCountry - we only need the iso2 from now on, so just store that
1006
1181
  if (this.selectedCountryData.iso2) {
1007
1182
  this.defaultCountry = this.selectedCountryData.iso2;
1008
1183
  }
1009
1184
 
1010
1185
  if (this.options.showFlags) {
1011
- this.selectedFlagInner.setAttribute('class', `iti__flag iti__${countryCode}`);
1186
+ this.selectedFlagInner.setAttribute(
1187
+ "class",
1188
+ `iti__flag iti__${countryCode}`
1189
+ );
1012
1190
  }
1013
1191
  // update the selected country's title attribute
1014
1192
  if (this.selectedFlag) {
1015
- const title = (countryCode) ? `${this.selectedCountryData.name}: +${this.selectedCountryData.dialCode}` : 'Unknown';
1016
- this.selectedFlag.setAttribute('title', title);
1193
+ const title = countryCode
1194
+ ? `${this.selectedCountryData.name}: +${this.selectedCountryData.dialCode}`
1195
+ : "Unknown";
1196
+ this.selectedFlag.setAttribute("title", title);
1017
1197
  }
1018
1198
 
1019
1199
  if (this.options.separateDialCode) {
1020
- const dialCode = this.selectedCountryData.dialCode ? `+${this.selectedCountryData.dialCode}` : '';
1200
+ const dialCode = this.selectedCountryData.dialCode
1201
+ ? `+${this.selectedCountryData.dialCode}`
1202
+ : "";
1021
1203
  this.selectedDialCode.innerHTML = dialCode;
1022
1204
  // offsetWidth is zero if input is in a hidden container during initialisation
1023
- const selectedFlagWidth = this.selectedFlag.offsetWidth || this._getHiddenSelectedFlagWidth();
1205
+ const selectedFlagWidth =
1206
+ this.selectedFlag.offsetWidth || this._getHiddenSelectedFlagWidth();
1024
1207
 
1025
1208
  // add 6px of padding after the grey selected-dial-code box, as this is what we use in the css
1026
1209
  this.telInput.style.paddingLeft = `${selectedFlagWidth + 6}px`;
@@ -1033,23 +1216,28 @@ class Iti {
1033
1216
  if (this.options.allowDropdown) {
1034
1217
  const prevItem = this.activeItem;
1035
1218
  if (prevItem) {
1036
- prevItem.classList.remove('iti__active');
1037
- prevItem.setAttribute('aria-selected', 'false');
1219
+ prevItem.classList.remove("iti__active");
1220
+ prevItem.setAttribute("aria-selected", "false");
1038
1221
  }
1039
1222
  if (countryCode) {
1040
1223
  // check if there is a preferred item first, else fall back to standard
1041
- const nextItem = this.countryList.querySelector(`#iti-${this.id}__item-${countryCode}-preferred`) || this.countryList.querySelector(`#iti-${this.id}__item-${countryCode}`);
1042
- nextItem.setAttribute('aria-selected', 'true');
1043
- nextItem.classList.add('iti__active');
1224
+ const nextItem =
1225
+ this.countryList.querySelector(
1226
+ `#iti-${this.id}__item-${countryCode}-preferred`
1227
+ ) ||
1228
+ this.countryList.querySelector(
1229
+ `#iti-${this.id}__item-${countryCode}`
1230
+ );
1231
+ nextItem.setAttribute("aria-selected", "true");
1232
+ nextItem.classList.add("iti__active");
1044
1233
  this.activeItem = nextItem;
1045
1234
  }
1046
1235
  }
1047
1236
 
1048
1237
  // return if the flag has changed or not
1049
- return (prevCountry.iso2 !== countryCode);
1238
+ return prevCountry.iso2 !== countryCode;
1050
1239
  }
1051
1240
 
1052
-
1053
1241
  // when the input is in a hidden container during initialisation, we must inject some markup
1054
1242
  // into the end of the DOM to calculate the correct offsetWidth
1055
1243
  // NOTE: this is only used when separateDialCode is enabled, so flagsContainer and selectedFlag
@@ -1058,7 +1246,7 @@ class Iti {
1058
1246
  // to get the right styling to apply, all we need is a shallow clone of the container,
1059
1247
  // and then to inject a deep clone of the selectedFlag element
1060
1248
  const containerClone = this.telInput.parentNode.cloneNode();
1061
- containerClone.style.visibility = 'hidden';
1249
+ containerClone.style.visibility = "hidden";
1062
1250
  document.body.appendChild(containerClone);
1063
1251
 
1064
1252
  const flagsContainerClone = this.flagsContainer.cloneNode();
@@ -1072,35 +1260,48 @@ class Iti {
1072
1260
  return width;
1073
1261
  }
1074
1262
 
1075
-
1076
1263
  // update the input placeholder to an example number from the currently selected country
1077
1264
  _updatePlaceholder() {
1078
- const shouldSetPlaceholder = (this.options.autoPlaceholder === 'aggressive') || (!this.hadInitialPlaceholder && this.options.autoPlaceholder === 'polite');
1265
+ const shouldSetPlaceholder =
1266
+ this.options.autoPlaceholder === "aggressive" ||
1267
+ (!this.hadInitialPlaceholder &&
1268
+ this.options.autoPlaceholder === "polite");
1079
1269
  if (window.intlTelInputUtils && shouldSetPlaceholder) {
1080
- const numberType = intlTelInputUtils.numberType[this.options.placeholderNumberType];
1081
- let placeholder = (this.selectedCountryData.iso2) ? intlTelInputUtils.getExampleNumber(this.selectedCountryData.iso2, this.options.nationalMode, numberType) : '';
1270
+ const numberType =
1271
+ intlTelInputUtils.numberType[this.options.placeholderNumberType];
1272
+ let placeholder = this.selectedCountryData.iso2
1273
+ ? intlTelInputUtils.getExampleNumber(
1274
+ this.selectedCountryData.iso2,
1275
+ this.options.nationalMode,
1276
+ numberType
1277
+ )
1278
+ : "";
1082
1279
 
1083
1280
  placeholder = this._beforeSetNumber(placeholder);
1084
- if (typeof this.options.customPlaceholder === 'function') {
1085
- placeholder = this.options.customPlaceholder(placeholder, this.selectedCountryData);
1281
+ if (typeof this.options.customPlaceholder === "function") {
1282
+ placeholder = this.options.customPlaceholder(
1283
+ placeholder,
1284
+ this.selectedCountryData
1285
+ );
1086
1286
  }
1087
- this.telInput.setAttribute('placeholder', placeholder);
1287
+ this.telInput.setAttribute("placeholder", placeholder);
1088
1288
  }
1089
1289
  }
1090
1290
 
1091
-
1092
1291
  // called when the user selects a list item from the dropdown
1093
1292
  _selectListItem(listItem) {
1094
1293
  // update selected flag and active list item
1095
- const flagChanged = this._setFlag(listItem.getAttribute('data-country-code'));
1294
+ const flagChanged = this._setFlag(
1295
+ listItem.getAttribute("data-country-code")
1296
+ );
1096
1297
  this._closeDropdown();
1097
1298
 
1098
- this._updateDialCode(listItem.getAttribute('data-dial-code'));
1299
+ this._updateDialCode(listItem.getAttribute("data-dial-code"));
1099
1300
 
1100
1301
  // focus the input
1101
1302
  this.telInput.focus();
1102
- // put cursor at end - this fix is required for FF and IE11 (with nationalMode=false i.e. auto
1103
- // inserting dial code), who try to put the cursor at the beginning the first time
1303
+ // put cursor at end - this fix is required for FF and IE11 (with auto inserting dial code),
1304
+ // who try to put the cursor at the beginning the first time
1104
1305
  const len = this.telInput.value.length;
1105
1306
  this.telInput.setSelectionRange(len, len);
1106
1307
 
@@ -1109,32 +1310,40 @@ class Iti {
1109
1310
  }
1110
1311
  }
1111
1312
 
1112
-
1113
1313
  // close the dropdown and unbind any listeners
1114
1314
  _closeDropdown() {
1115
- this.countryList.classList.add('iti__hide');
1116
- this.selectedFlag.setAttribute('aria-expanded', 'false');
1117
- this.selectedFlag.removeAttribute('aria-activedescendant');
1315
+ this.countryList.classList.add("iti__hide");
1316
+ this.selectedFlag.setAttribute("aria-expanded", "false");
1317
+ this.selectedFlag.removeAttribute("aria-activedescendant");
1118
1318
 
1119
1319
  // update the arrow
1120
- this.dropdownArrow.classList.remove('iti__arrow--up');
1320
+ this.dropdownArrow.classList.remove("iti__arrow--up");
1121
1321
 
1122
1322
  // unbind key events
1123
- document.removeEventListener('keydown', this._handleKeydownOnDropdown);
1124
- document.documentElement.removeEventListener('click', this._handleClickOffToClose);
1125
- this.countryList.removeEventListener('mouseover', this._handleMouseoverCountryList);
1126
- this.countryList.removeEventListener('click', this._handleClickCountryList);
1323
+ document.removeEventListener("keydown", this._handleKeydownOnDropdown);
1324
+ document.documentElement.removeEventListener(
1325
+ "click",
1326
+ this._handleClickOffToClose
1327
+ );
1328
+ this.countryList.removeEventListener(
1329
+ "mouseover",
1330
+ this._handleMouseoverCountryList
1331
+ );
1332
+ this.countryList.removeEventListener("click", this._handleClickCountryList);
1127
1333
 
1128
1334
  // remove menu from container
1129
1335
  if (this.options.dropdownContainer) {
1130
- if (!this.isMobile) window.removeEventListener('scroll', this._handleWindowScroll);
1131
- if (this.dropdown.parentNode) this.dropdown.parentNode.removeChild(this.dropdown);
1336
+ if (!this.isMobile) {
1337
+ window.removeEventListener("scroll", this._handleWindowScroll);
1338
+ }
1339
+ if (this.dropdown.parentNode) {
1340
+ this.dropdown.parentNode.removeChild(this.dropdown);
1341
+ }
1132
1342
  }
1133
1343
 
1134
- this._trigger('close:countrydropdown');
1344
+ this._trigger("close:countrydropdown");
1135
1345
  }
1136
1346
 
1137
-
1138
1347
  // check if an element is visible within it's container, else scroll until it is
1139
1348
  _scrollTo(element, middle) {
1140
1349
  const container = this.countryList;
@@ -1147,21 +1356,24 @@ class Iti {
1147
1356
  const elementTop = element.getBoundingClientRect().top + windowTop;
1148
1357
  const elementBottom = elementTop + elementHeight;
1149
1358
  let newScrollTop = elementTop - containerTop + container.scrollTop;
1150
- const middleOffset = (containerHeight / 2) - (elementHeight / 2);
1359
+ const middleOffset = containerHeight / 2 - elementHeight / 2;
1151
1360
 
1152
1361
  if (elementTop < containerTop) {
1153
1362
  // scroll up
1154
- if (middle) newScrollTop -= middleOffset;
1363
+ if (middle) {
1364
+ newScrollTop -= middleOffset;
1365
+ }
1155
1366
  container.scrollTop = newScrollTop;
1156
1367
  } else if (elementBottom > containerBottom) {
1157
1368
  // scroll down
1158
- if (middle) newScrollTop += middleOffset;
1369
+ if (middle) {
1370
+ newScrollTop += middleOffset;
1371
+ }
1159
1372
  const heightDifference = containerHeight - elementHeight;
1160
1373
  container.scrollTop = newScrollTop - heightDifference;
1161
1374
  }
1162
1375
  }
1163
1376
 
1164
-
1165
1377
  // replace any existing dial code with the new one
1166
1378
  // Note: called from _selectListItem and setCountry
1167
1379
  _updateDialCode(newDialCodeBare) {
@@ -1170,8 +1382,8 @@ class Iti {
1170
1382
  const newDialCode = `+${newDialCodeBare}`;
1171
1383
 
1172
1384
  let newNumber;
1173
- if (inputVal.charAt(0) === '+') {
1174
- // there's a plus so we're dealing with a replacement (doesn't matter if nationalMode or not)
1385
+ if (inputVal.charAt(0) === "+") {
1386
+ // there's a plus so we're dealing with a replacement
1175
1387
  const prevDialCode = this._getDialCode(inputVal);
1176
1388
  if (prevDialCode) {
1177
1389
  // current number contains a valid dial code, so replace it
@@ -1193,14 +1405,13 @@ class Iti {
1193
1405
  }
1194
1406
  }
1195
1407
 
1196
-
1197
1408
  // try and extract a valid international dial code from a full telephone number
1198
1409
  // Note: returns the raw string inc plus character and any whitespace/dots etc
1199
1410
  _getDialCode(number, includeAreaCode) {
1200
- let dialCode = '';
1411
+ let dialCode = "";
1201
1412
  // only interested in international numbers (starting with a plus)
1202
- if (number.charAt(0) === '+') {
1203
- let numericChars = '';
1413
+ if (number.charAt(0) === "+") {
1414
+ let numericChars = "";
1204
1415
  // iterate over chars
1205
1416
  for (let i = 0; i < number.length; i++) {
1206
1417
  const c = number.charAt(i);
@@ -1230,7 +1441,6 @@ class Iti {
1230
1441
  return dialCode;
1231
1442
  }
1232
1443
 
1233
-
1234
1444
  // get the input val, adding the dial code if separateDialCode is enabled
1235
1445
  _getFullNumber() {
1236
1446
  const val = this.telInput.value.trim();
@@ -1238,16 +1448,20 @@ class Iti {
1238
1448
  let prefix;
1239
1449
  const numericVal = this._getNumeric(val);
1240
1450
 
1241
- if (this.options.separateDialCode && val.charAt(0) !== '+' && dialCode && numericVal) {
1451
+ if (
1452
+ this.options.separateDialCode &&
1453
+ val.charAt(0) !== "+" &&
1454
+ dialCode &&
1455
+ numericVal
1456
+ ) {
1242
1457
  // when using separateDialCode, it is visible so is effectively part of the typed number
1243
1458
  prefix = `+${dialCode}`;
1244
1459
  } else {
1245
- prefix = '';
1460
+ prefix = "";
1246
1461
  }
1247
1462
  return prefix + val;
1248
1463
  }
1249
1464
 
1250
-
1251
1465
  // remove the dial code if separateDialCode is enabled
1252
1466
  // also cap the length if the input has a maxlength attribute
1253
1467
  _beforeSetNumber(originalNumber) {
@@ -1262,7 +1476,10 @@ class Iti {
1262
1476
  // some NANP numbers will have a hyphen e.g. +1 684-733-1234 - in both cases we want to get
1263
1477
  // rid of it
1264
1478
  // NOTE: don't just trim all non-numerics as may want to preserve an open parenthesis etc
1265
- const start = (number[dialCode.length] === ' ' || number[dialCode.length] === '-') ? dialCode.length + 1 : dialCode.length;
1479
+ const start =
1480
+ number[dialCode.length] === " " || number[dialCode.length] === "-"
1481
+ ? dialCode.length + 1
1482
+ : dialCode.length;
1266
1483
  number = number.substr(start);
1267
1484
  }
1268
1485
  }
@@ -1270,21 +1487,18 @@ class Iti {
1270
1487
  return this._cap(number);
1271
1488
  }
1272
1489
 
1273
-
1274
1490
  // trigger the 'countrychange' event
1275
1491
  _triggerCountryChange() {
1276
- this._trigger('countrychange');
1492
+ this._trigger("countrychange");
1277
1493
  }
1278
1494
 
1279
-
1280
1495
  /**************************
1281
1496
  * SECRET PUBLIC METHODS
1282
1497
  **************************/
1283
1498
 
1284
-
1285
1499
  // this is called when the geoip call returns
1286
1500
  handleAutoCountry() {
1287
- if (this.options.initialCountry === 'auto') {
1501
+ if (this.options.initialCountry === "auto") {
1288
1502
  // we must set this even if there is an initial val in the input: in case the initial val is
1289
1503
  // invalid and they delete it - they should see their auto country
1290
1504
  this.defaultCountry = window.intlTelInputGlobals.autoCountry;
@@ -1296,7 +1510,6 @@ class Iti {
1296
1510
  }
1297
1511
  }
1298
1512
 
1299
-
1300
1513
  // this is called when the utils request completes
1301
1514
  handleUtils() {
1302
1515
  // if the request was successful
@@ -1310,12 +1523,10 @@ class Iti {
1310
1523
  this.resolveUtilsScriptPromise();
1311
1524
  }
1312
1525
 
1313
-
1314
1526
  /********************
1315
1527
  * PUBLIC METHODS
1316
1528
  ********************/
1317
1529
 
1318
-
1319
1530
  // remove plugin
1320
1531
  destroy() {
1321
1532
  const { form } = this.telInput;
@@ -1323,29 +1534,41 @@ class Iti {
1323
1534
  if (this.options.allowDropdown) {
1324
1535
  // make sure the dropdown is closed (and unbind listeners)
1325
1536
  this._closeDropdown();
1326
- this.selectedFlag.removeEventListener('click', this._handleClickSelectedFlag);
1327
- this.flagsContainer.removeEventListener('keydown', this._handleFlagsContainerKeydown);
1537
+ this.selectedFlag.removeEventListener(
1538
+ "click",
1539
+ this._handleClickSelectedFlag
1540
+ );
1541
+ this.flagsContainer.removeEventListener(
1542
+ "keydown",
1543
+ this._handleFlagsContainerKeydown
1544
+ );
1328
1545
  // label click hack
1329
1546
  const label = this._getClosestLabel();
1330
- if (label) label.removeEventListener('click', this._handleLabelClick);
1547
+ if (label) {
1548
+ label.removeEventListener("click", this._handleLabelClick);
1549
+ }
1331
1550
  }
1332
1551
 
1333
1552
  // unbind hiddenInput listeners
1334
- if (this.hiddenInput && form) form.removeEventListener('submit', this._handleHiddenInputSubmit);
1553
+ if (this.hiddenInput && form) {
1554
+ form.removeEventListener("submit", this._handleHiddenInputSubmit);
1555
+ }
1335
1556
 
1336
1557
  // unbind autoInsertDialCode listeners
1337
1558
  if (this.options.autoInsertDialCode) {
1338
- if (form) form.removeEventListener('submit', this._handleSubmitOrBlurEvent);
1339
- this.telInput.removeEventListener('blur', this._handleSubmitOrBlurEvent);
1559
+ if (form) {
1560
+ form.removeEventListener("submit", this._handleSubmitOrBlurEvent);
1561
+ }
1562
+ this.telInput.removeEventListener("blur", this._handleSubmitOrBlurEvent);
1340
1563
  }
1341
1564
 
1342
1565
  // unbind key events, and cut/paste events
1343
- this.telInput.removeEventListener('keyup', this._handleKeyupEvent);
1344
- this.telInput.removeEventListener('cut', this._handleClipboardEvent);
1345
- this.telInput.removeEventListener('paste', this._handleClipboardEvent);
1566
+ this.telInput.removeEventListener("keyup", this._handleKeyupEvent);
1567
+ this.telInput.removeEventListener("cut", this._handleClipboardEvent);
1568
+ this.telInput.removeEventListener("paste", this._handleClipboardEvent);
1346
1569
 
1347
1570
  // remove attribute of id instance: data-intl-tel-input-id
1348
- this.telInput.removeAttribute('data-intl-tel-input-id');
1571
+ this.telInput.removeAttribute("data-intl-tel-input-id");
1349
1572
 
1350
1573
  // remove markup (but leave the original input)
1351
1574
  const wrapper = this.telInput.parentNode;
@@ -1355,41 +1578,46 @@ class Iti {
1355
1578
  delete window.intlTelInputGlobals.instances[this.id];
1356
1579
  }
1357
1580
 
1358
-
1359
1581
  // get the extension from the current number
1360
1582
  getExtension() {
1361
1583
  if (window.intlTelInputUtils) {
1362
- return intlTelInputUtils.getExtension(this._getFullNumber(), this.selectedCountryData.iso2);
1584
+ return intlTelInputUtils.getExtension(
1585
+ this._getFullNumber(),
1586
+ this.selectedCountryData.iso2
1587
+ );
1363
1588
  }
1364
- return '';
1589
+ return "";
1365
1590
  }
1366
1591
 
1367
-
1368
1592
  // format the number to the given format
1369
1593
  getNumber(format) {
1370
1594
  if (window.intlTelInputUtils) {
1371
1595
  const { iso2 } = this.selectedCountryData;
1372
- return intlTelInputUtils.formatNumber(this._getFullNumber(), iso2, format);
1596
+ return intlTelInputUtils.formatNumber(
1597
+ this._getFullNumber(),
1598
+ iso2,
1599
+ format
1600
+ );
1373
1601
  }
1374
- return '';
1602
+ return "";
1375
1603
  }
1376
1604
 
1377
-
1378
1605
  // get the type of the entered number e.g. landline/mobile
1379
1606
  getNumberType() {
1380
1607
  if (window.intlTelInputUtils) {
1381
- return intlTelInputUtils.getNumberType(this._getFullNumber(), this.selectedCountryData.iso2);
1608
+ return intlTelInputUtils.getNumberType(
1609
+ this._getFullNumber(),
1610
+ this.selectedCountryData.iso2
1611
+ );
1382
1612
  }
1383
1613
  return -99;
1384
1614
  }
1385
1615
 
1386
-
1387
1616
  // get the country data for the currently selected flag
1388
1617
  getSelectedCountryData() {
1389
1618
  return this.selectedCountryData;
1390
1619
  }
1391
1620
 
1392
-
1393
1621
  // get the validation error
1394
1622
  getValidationError() {
1395
1623
  if (window.intlTelInputUtils) {
@@ -1399,15 +1627,14 @@ class Iti {
1399
1627
  return -99;
1400
1628
  }
1401
1629
 
1402
-
1403
1630
  // validate the input val - assumes the global function isValidNumber (from utilsScript)
1404
1631
  isValidNumber() {
1405
1632
  const val = this._getFullNumber().trim();
1406
- const countryCode = (this.options.nationalMode) ? this.selectedCountryData.iso2 : '';
1407
- return (window.intlTelInputUtils ? intlTelInputUtils.isValidNumber(val, countryCode) : null);
1633
+ return window.intlTelInputUtils
1634
+ ? intlTelInputUtils.isValidNumber(val, this.selectedCountryData.iso2)
1635
+ : null;
1408
1636
  }
1409
1637
 
1410
-
1411
1638
  // update the selected flag, and update the input val accordingly
1412
1639
  setCountry(originalCountryCode) {
1413
1640
  const countryCode = originalCountryCode.toLowerCase();
@@ -1419,7 +1646,6 @@ class Iti {
1419
1646
  }
1420
1647
  }
1421
1648
 
1422
-
1423
1649
  // set the input value and update the flag
1424
1650
  setNumber(number) {
1425
1651
  // we must update the flag first, which updates this.selectedCountryData, which is used for
@@ -1438,57 +1664,61 @@ class Iti {
1438
1664
  }
1439
1665
  }
1440
1666
 
1441
-
1442
1667
  /********************
1443
1668
  * STATIC METHODS
1444
1669
  ********************/
1445
1670
 
1446
-
1447
1671
  // get the country data object
1448
1672
  intlTelInputGlobals.getCountryData = () => allCountries;
1449
1673
 
1450
-
1451
1674
  // inject a <script> element to load utils.js
1452
1675
  const injectScript = (path, handleSuccess, handleFailure) => {
1453
1676
  // inject a new script element into the page
1454
- const script = document.createElement('script');
1677
+ const script = document.createElement("script");
1455
1678
  script.onload = () => {
1456
- forEachInstance('handleUtils');
1457
- if (handleSuccess) handleSuccess();
1679
+ forEachInstance("handleUtils");
1680
+ if (handleSuccess) {
1681
+ handleSuccess();
1682
+ }
1458
1683
  };
1459
1684
  script.onerror = () => {
1460
- forEachInstance('rejectUtilsScriptPromise');
1461
- if (handleFailure) handleFailure();
1685
+ forEachInstance("rejectUtilsScriptPromise");
1686
+ if (handleFailure) {
1687
+ handleFailure();
1688
+ }
1462
1689
  };
1463
- script.className = 'iti-load-utils';
1690
+ script.className = "iti-load-utils";
1464
1691
  script.async = true;
1465
1692
  script.src = path;
1466
1693
  document.body.appendChild(script);
1467
1694
  };
1468
1695
 
1469
-
1470
1696
  // load the utils script
1471
1697
  intlTelInputGlobals.loadUtils = (path) => {
1472
1698
  // 2 options:
1473
1699
  // 1) not already started loading (start)
1474
1700
  // 2) already started loading (do nothing - just wait for the onload callback to fire, which will
1475
1701
  // trigger handleUtils on all instances, invoking their resolveUtilsScriptPromise functions)
1476
- if (!window.intlTelInputUtils && !window.intlTelInputGlobals.startedLoadingUtilsScript) {
1702
+ if (
1703
+ !window.intlTelInputUtils &&
1704
+ !window.intlTelInputGlobals.startedLoadingUtilsScript
1705
+ ) {
1477
1706
  // only do this once
1478
1707
  window.intlTelInputGlobals.startedLoadingUtilsScript = true;
1479
1708
 
1480
1709
  // if we have promises, then return a promise
1481
- if (typeof Promise !== 'undefined') {
1482
- return new Promise((resolve, reject) => injectScript(path, resolve, reject));
1710
+ if (typeof Promise !== "undefined") {
1711
+ return new Promise((resolve, reject) =>
1712
+ injectScript(path, resolve, reject)
1713
+ );
1483
1714
  }
1484
1715
  injectScript(path);
1485
1716
  }
1486
1717
  return null;
1487
1718
  };
1488
1719
 
1489
-
1490
1720
  // default options
1491
1721
  intlTelInputGlobals.defaults = defaults;
1492
1722
 
1493
1723
  // version
1494
- intlTelInputGlobals.version = '<%= version %>';
1724
+ intlTelInputGlobals.version = "<%= version %>";