intl-tel-input 18.5.2 → 19.0.0
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.
- package/README.md +42 -28
- package/build/css/demo.css +1 -1
- package/build/css/intlTelInput.css +28 -20
- package/build/js/data.js +1 -1
- package/build/js/data.min.js +1 -1
- package/build/js/intlTelInput-jquery.js +159 -154
- package/build/js/intlTelInput-jquery.min.js +3 -3
- package/build/js/intlTelInput.js +159 -154
- package/build/js/intlTelInput.min.js +3 -3
- package/composer.json +1 -1
- package/demo.html +5 -5
- package/grunt/replace.js +1 -7
- package/package.json +1 -1
- package/spec.html +6 -4
- package/src/css/demo.scss +1 -1
- package/src/css/intlTelInput.scss +41 -30
- package/src/js/intlTelInput.js +77 -128
- package/src/spec/helpers/helpers.js +23 -10
- package/src/spec/tests/core/countrychangeEvent.js +1 -1
- package/src/spec/tests/core/dropdownShortcuts.js +3 -2
- package/src/spec/tests/core/initialValues.js +2 -3
- package/src/spec/tests/methods/getSelectedCountryData.js +1 -1
- package/src/spec/tests/methods/isValidNumber.js +15 -32
- package/src/spec/tests/methods/isValidNumberPrecise.js +73 -0
- package/src/spec/tests/methods/setCountry.js +4 -4
- package/src/spec/tests/options/allowDropdown.js +3 -3
- package/src/spec/tests/options/autoInsertDialCode.js +1 -3
- package/src/spec/tests/options/autoPlaceholder.js +5 -5
- package/src/spec/tests/options/{customContainer.js → containerClass.js} +3 -3
- package/src/spec/tests/options/countrySearch.js +63 -0
- package/src/spec/tests/options/customPlaceholder.js +1 -1
- package/src/spec/tests/options/preferredCountries.js +3 -1
- package/src/spec/tests/options/{separateDialCode.js → showSelectedDialCode.js} +7 -7
- package/src/spec/tests/methods/isPossibleNumber.js +0 -56
package/src/js/intlTelInput.js
CHANGED
|
@@ -23,9 +23,9 @@ const defaults = {
|
|
|
23
23
|
// add a placeholder in the input with an example number for the selected country
|
|
24
24
|
autoPlaceholder: "polite",
|
|
25
25
|
// add a country search input at the top of the dropdown
|
|
26
|
-
countrySearch:
|
|
26
|
+
countrySearch: true,
|
|
27
27
|
// modify the parentClass
|
|
28
|
-
|
|
28
|
+
containerClass: "",
|
|
29
29
|
// modify the auto placeholder
|
|
30
30
|
customPlaceholder: null,
|
|
31
31
|
// append menu to specified element
|
|
@@ -33,29 +33,29 @@ const defaults = {
|
|
|
33
33
|
// don't display these countries
|
|
34
34
|
excludeCountries: [],
|
|
35
35
|
// fix the dropdown width to the input width (rather than being as wide as the longest country name)
|
|
36
|
-
fixDropdownWidth:
|
|
36
|
+
fixDropdownWidth: true,
|
|
37
37
|
// format the input value during initialisation and on setNumber
|
|
38
38
|
formatOnDisplay: true,
|
|
39
39
|
// geoIp lookup function
|
|
40
40
|
geoIpLookup: null,
|
|
41
41
|
// inject a hidden input with this name, and on submit, populate it with the result of getNumber
|
|
42
|
-
hiddenInput:
|
|
42
|
+
hiddenInput: null,
|
|
43
|
+
// internationalise the plugin text e.g. search input placeholder, country names
|
|
44
|
+
i18n: {},
|
|
43
45
|
// initial country
|
|
44
46
|
initialCountry: "",
|
|
45
|
-
// localized country names e.g. { 'de': 'Deutschland' }
|
|
46
|
-
localizedCountries: null,
|
|
47
47
|
// national vs international formatting for numbers e.g. placeholders and displaying existing numbers
|
|
48
48
|
nationalMode: true,
|
|
49
49
|
// display only these countries
|
|
50
50
|
onlyCountries: [],
|
|
51
51
|
// number type to use for placeholders
|
|
52
52
|
placeholderNumberType: "MOBILE",
|
|
53
|
-
// the countries at the top of the list
|
|
54
|
-
preferredCountries: [
|
|
55
|
-
//
|
|
56
|
-
separateDialCode: false,
|
|
57
|
-
// option to hide the flags - must be used with separateDialCode, or allowDropdown=false
|
|
53
|
+
// the countries at the top of the list
|
|
54
|
+
preferredCountries: [],
|
|
55
|
+
// option to hide the flags - must be used with showSelectedDialCode, or allowDropdown=false
|
|
58
56
|
showFlags: true,
|
|
57
|
+
// display the international dial code next to the selected flag
|
|
58
|
+
showSelectedDialCode: false,
|
|
59
59
|
// use full screen popup instead of dropdown for country list
|
|
60
60
|
useFullscreenPopup:
|
|
61
61
|
typeof navigator !== "undefined" && typeof window !== "undefined"
|
|
@@ -90,26 +90,16 @@ const regionlessNanpNumbers = [
|
|
|
90
90
|
"889"
|
|
91
91
|
];
|
|
92
92
|
|
|
93
|
-
// utility function to iterate over an object. can't use Object.entries or native forEach because
|
|
94
|
-
// of IE11
|
|
95
|
-
const forEachProp = (obj, callback) => {
|
|
96
|
-
const keys = Object.keys(obj);
|
|
97
|
-
for (let i = 0; i < keys.length; i++) {
|
|
98
|
-
callback(keys[i], obj[keys[i]]);
|
|
99
|
-
}
|
|
100
|
-
};
|
|
101
|
-
|
|
102
93
|
// run a method on each instance of the plugin
|
|
103
94
|
const forEachInstance = (method) => {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
});
|
|
95
|
+
const { instances } = window.intlTelInputGlobals;
|
|
96
|
+
Object.values(instances).forEach((instance) => instance[method]());
|
|
107
97
|
};
|
|
108
98
|
|
|
109
99
|
// this is our plugin class that we will create an instance of
|
|
110
100
|
// eslint-disable-next-line no-unused-vars
|
|
111
101
|
class Iti {
|
|
112
|
-
constructor(input,
|
|
102
|
+
constructor(input, customOptions = {}) {
|
|
113
103
|
this.id = id++;
|
|
114
104
|
this.telInput = input;
|
|
115
105
|
|
|
@@ -117,15 +107,7 @@ class Iti {
|
|
|
117
107
|
this.highlightedItem = null;
|
|
118
108
|
|
|
119
109
|
// process specified options / defaults
|
|
120
|
-
|
|
121
|
-
const customOptions = options || {};
|
|
122
|
-
this.options = {};
|
|
123
|
-
forEachProp(defaults, (key, value) => {
|
|
124
|
-
this.options[key] = customOptions.hasOwnProperty(key)
|
|
125
|
-
? customOptions[key]
|
|
126
|
-
: value;
|
|
127
|
-
});
|
|
128
|
-
|
|
110
|
+
this.options = Object.assign({}, defaults, customOptions);
|
|
129
111
|
this.hadInitialPlaceholder = Boolean(input.getAttribute("placeholder"));
|
|
130
112
|
}
|
|
131
113
|
|
|
@@ -145,15 +127,15 @@ class Iti {
|
|
|
145
127
|
this.options.autoInsertDialCode = false;
|
|
146
128
|
}
|
|
147
129
|
|
|
148
|
-
// if
|
|
149
|
-
if (this.options.
|
|
130
|
+
// if showSelectedDialCode enabled, do not insert dial codes
|
|
131
|
+
if (this.options.showSelectedDialCode) {
|
|
150
132
|
this.options.autoInsertDialCode = false;
|
|
151
133
|
}
|
|
152
134
|
|
|
153
135
|
// force showFlags=true if there's a dropdown and we're not displaying the dial code,
|
|
154
136
|
// as otherwise you just have a down arrow on it's own which doesn't make sense
|
|
155
137
|
const forceShowFlags =
|
|
156
|
-
this.options.allowDropdown && !this.options.
|
|
138
|
+
this.options.allowDropdown && !this.options.showSelectedDialCode;
|
|
157
139
|
if (!this.options.showFlags && forceShowFlags) {
|
|
158
140
|
this.options.showFlags = true;
|
|
159
141
|
}
|
|
@@ -221,13 +203,11 @@ class Iti {
|
|
|
221
203
|
// process the preferredCountries
|
|
222
204
|
this._processPreferredCountries();
|
|
223
205
|
|
|
224
|
-
// translate
|
|
225
|
-
|
|
226
|
-
this._translateCountriesByLocale();
|
|
227
|
-
}
|
|
206
|
+
// translate country names according to i18n option
|
|
207
|
+
this._translateCountryNames();
|
|
228
208
|
|
|
229
209
|
// sort countries by name
|
|
230
|
-
if (this.options.onlyCountries.length || this.options.
|
|
210
|
+
if (this.options.onlyCountries.length || this.options.i18n) {
|
|
231
211
|
this.countries.sort(this._countryNameSort);
|
|
232
212
|
}
|
|
233
213
|
}
|
|
@@ -274,11 +254,11 @@ class Iti {
|
|
|
274
254
|
}
|
|
275
255
|
|
|
276
256
|
// Translate Countries by object literal provided on config
|
|
277
|
-
|
|
257
|
+
_translateCountryNames() {
|
|
278
258
|
for (let i = 0; i < this.countries.length; i++) {
|
|
279
259
|
const iso = this.countries[i].iso2.toLowerCase();
|
|
280
|
-
if (this.options.
|
|
281
|
-
this.countries[i].name = this.options.
|
|
260
|
+
if (this.options.i18n.hasOwnProperty(iso)) {
|
|
261
|
+
this.countries[i].name = this.options.i18n[iso];
|
|
282
262
|
}
|
|
283
263
|
}
|
|
284
264
|
}
|
|
@@ -354,7 +334,7 @@ class Iti {
|
|
|
354
334
|
_createEl(name, attrs, container) {
|
|
355
335
|
const el = document.createElement(name);
|
|
356
336
|
if (attrs) {
|
|
357
|
-
|
|
337
|
+
Object.entries(attrs).forEach(([key, value]) => el.setAttribute(key, value));
|
|
358
338
|
}
|
|
359
339
|
if (container) {
|
|
360
340
|
container.appendChild(el);
|
|
@@ -379,9 +359,9 @@ class Iti {
|
|
|
379
359
|
|
|
380
360
|
const {
|
|
381
361
|
allowDropdown,
|
|
382
|
-
|
|
362
|
+
showSelectedDialCode,
|
|
383
363
|
showFlags,
|
|
384
|
-
|
|
364
|
+
containerClass,
|
|
385
365
|
hiddenInput,
|
|
386
366
|
dropdownContainer,
|
|
387
367
|
fixDropdownWidth,
|
|
@@ -394,23 +374,23 @@ class Iti {
|
|
|
394
374
|
if (allowDropdown) {
|
|
395
375
|
parentClass += " iti--allow-dropdown";
|
|
396
376
|
}
|
|
397
|
-
if (
|
|
398
|
-
parentClass += " iti--
|
|
377
|
+
if (showSelectedDialCode) {
|
|
378
|
+
parentClass += " iti--show-selected-dial-code";
|
|
399
379
|
}
|
|
400
380
|
if (showFlags) {
|
|
401
381
|
parentClass += " iti--show-flags";
|
|
402
382
|
}
|
|
403
|
-
if (
|
|
404
|
-
parentClass +=
|
|
383
|
+
if (containerClass) {
|
|
384
|
+
parentClass += ` ${containerClass}`;
|
|
405
385
|
}
|
|
406
|
-
if (
|
|
407
|
-
parentClass +=
|
|
386
|
+
if (!useFullscreenPopup) {
|
|
387
|
+
parentClass += " iti--inline-dropdown";
|
|
408
388
|
}
|
|
409
389
|
|
|
410
390
|
const wrapper = this._createEl("div", { class: parentClass });
|
|
411
391
|
this.telInput.parentNode.insertBefore(wrapper, this.telInput);
|
|
412
|
-
// only hide the flagsContainer if allowDropdown, showFlags and
|
|
413
|
-
const showFlagsContainer = allowDropdown || showFlags ||
|
|
392
|
+
// only hide the flagsContainer if allowDropdown, showFlags and showSelectedDialCode are all false
|
|
393
|
+
const showFlagsContainer = allowDropdown || showFlags || showSelectedDialCode;
|
|
414
394
|
if (showFlagsContainer) {
|
|
415
395
|
this.flagsContainer = this._createEl(
|
|
416
396
|
"div",
|
|
@@ -433,7 +413,7 @@ class Iti {
|
|
|
433
413
|
"aria-haspopup": "listbox",
|
|
434
414
|
"aria-controls": `iti-${this.id}__country-listbox`,
|
|
435
415
|
"aria-expanded": "false",
|
|
436
|
-
"aria-label": "
|
|
416
|
+
"aria-label": this.options.i18n.selectedCountryAriaLabel || "Selected country"
|
|
437
417
|
})
|
|
438
418
|
},
|
|
439
419
|
this.flagsContainer
|
|
@@ -451,7 +431,7 @@ class Iti {
|
|
|
451
431
|
this.selectedFlag.setAttribute("aria-disabled", "true");
|
|
452
432
|
}
|
|
453
433
|
|
|
454
|
-
if (
|
|
434
|
+
if (showSelectedDialCode) {
|
|
455
435
|
this.selectedDialCode = this._createEl(
|
|
456
436
|
"div",
|
|
457
437
|
{ class: "iti__selected-dial-code" },
|
|
@@ -471,8 +451,9 @@ class Iti {
|
|
|
471
451
|
this.selectedFlag
|
|
472
452
|
);
|
|
473
453
|
|
|
454
|
+
const extraClasses = fixDropdownWidth ? "" : "iti--flexible-dropdown-width";
|
|
474
455
|
this.dropdownContent = this._createEl("div", {
|
|
475
|
-
class:
|
|
456
|
+
class: `iti__dropdown-content iti__hide ${extraClasses}`
|
|
476
457
|
});
|
|
477
458
|
|
|
478
459
|
if (countrySearch) {
|
|
@@ -481,7 +462,7 @@ class Iti {
|
|
|
481
462
|
{
|
|
482
463
|
type: "text",
|
|
483
464
|
class: "iti__search-input",
|
|
484
|
-
placeholder: "Search"
|
|
465
|
+
placeholder: this.options.i18n.searchPlaceholder || "Search"
|
|
485
466
|
},
|
|
486
467
|
this.dropdownContent
|
|
487
468
|
);
|
|
@@ -494,7 +475,7 @@ class Iti {
|
|
|
494
475
|
class: "iti__country-list",
|
|
495
476
|
id: `iti-${this.id}__country-listbox`,
|
|
496
477
|
role: "listbox",
|
|
497
|
-
"aria-label": "List of countries"
|
|
478
|
+
"aria-label": this.options.i18n.countryListAriaLabel || "List of countries"
|
|
498
479
|
},
|
|
499
480
|
this.dropdownContent
|
|
500
481
|
);
|
|
@@ -516,6 +497,8 @@ class Iti {
|
|
|
516
497
|
let dropdownClasses = "iti iti--container";
|
|
517
498
|
if (useFullscreenPopup) {
|
|
518
499
|
dropdownClasses += " iti--fullscreen-popup";
|
|
500
|
+
} else {
|
|
501
|
+
dropdownClasses += " iti--inline-dropdown";
|
|
519
502
|
}
|
|
520
503
|
if (countrySearch) {
|
|
521
504
|
dropdownClasses += " iti--country-search";
|
|
@@ -528,16 +511,8 @@ class Iti {
|
|
|
528
511
|
}
|
|
529
512
|
|
|
530
513
|
if (hiddenInput) {
|
|
531
|
-
|
|
532
|
-
const
|
|
533
|
-
if (name) {
|
|
534
|
-
const i = name.lastIndexOf("[");
|
|
535
|
-
// if input name contains square brackets, then give the hidden input the same name,
|
|
536
|
-
// replacing the contents of the last set of brackets with the given hiddenInput name
|
|
537
|
-
if (i !== -1) {
|
|
538
|
-
hiddenInputName = `${name.substr(0, i)}[${hiddenInputName}]`;
|
|
539
|
-
}
|
|
540
|
-
}
|
|
514
|
+
const telInputName = this.telInput.getAttribute("name");
|
|
515
|
+
const hiddenInputName = hiddenInput(telInputName);
|
|
541
516
|
this.hiddenInput = this._createEl("input", {
|
|
542
517
|
type: "hidden",
|
|
543
518
|
name: hiddenInputName
|
|
@@ -665,15 +640,6 @@ class Iti {
|
|
|
665
640
|
}
|
|
666
641
|
}
|
|
667
642
|
|
|
668
|
-
// iterate through parent nodes to find the closest label ancestor, if it exists
|
|
669
|
-
_getClosestLabel() {
|
|
670
|
-
let el = this.telInput;
|
|
671
|
-
while (el && el.tagName !== "LABEL") {
|
|
672
|
-
el = el.parentNode;
|
|
673
|
-
}
|
|
674
|
-
return el;
|
|
675
|
-
}
|
|
676
|
-
|
|
677
643
|
// initialise the dropdown listeners
|
|
678
644
|
_initDropdownListeners() {
|
|
679
645
|
// hack for input nested inside label (which is valid markup): clicking the selected-flag to
|
|
@@ -687,7 +653,7 @@ class Iti {
|
|
|
687
653
|
e.preventDefault();
|
|
688
654
|
}
|
|
689
655
|
};
|
|
690
|
-
const label = this.
|
|
656
|
+
const label = this.telInput.closest("label");
|
|
691
657
|
if (label) {
|
|
692
658
|
label.addEventListener("click", this._handleLabelClick);
|
|
693
659
|
}
|
|
@@ -850,9 +816,10 @@ class Iti {
|
|
|
850
816
|
|
|
851
817
|
// trigger a custom event on the input
|
|
852
818
|
_trigger(name) {
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
819
|
+
const e = new Event(name, {
|
|
820
|
+
bubbles: true,
|
|
821
|
+
cancelable: true
|
|
822
|
+
});
|
|
856
823
|
this.telInput.dispatchEvent(e);
|
|
857
824
|
}
|
|
858
825
|
|
|
@@ -894,7 +861,7 @@ class Iti {
|
|
|
894
861
|
}
|
|
895
862
|
}
|
|
896
863
|
|
|
897
|
-
// decide
|
|
864
|
+
// decide if should position dropdown above or below input (depends on position within viewport, and scroll)
|
|
898
865
|
_setDropdownPosition() {
|
|
899
866
|
if (this.options.dropdownContainer) {
|
|
900
867
|
this.options.dropdownContainer.appendChild(this.dropdown);
|
|
@@ -903,8 +870,7 @@ class Iti {
|
|
|
903
870
|
if (!this.options.useFullscreenPopup) {
|
|
904
871
|
const pos = this.telInput.getBoundingClientRect();
|
|
905
872
|
// windowTop from https://stackoverflow.com/a/14384091/217866
|
|
906
|
-
const windowTop =
|
|
907
|
-
window.pageYOffset || document.documentElement.scrollTop;
|
|
873
|
+
const windowTop = document.documentElement.scrollTop;
|
|
908
874
|
const inputTop = pos.top + windowTop;
|
|
909
875
|
const dropdownHeight = this.dropdownContent.offsetHeight;
|
|
910
876
|
// dropdownFitsBelow = (dropdownBottom < windowBottom)
|
|
@@ -943,27 +909,13 @@ class Iti {
|
|
|
943
909
|
}
|
|
944
910
|
}
|
|
945
911
|
|
|
946
|
-
// iterate through parent nodes to find the closest list item
|
|
947
|
-
_getClosestListItem(target) {
|
|
948
|
-
let el = target;
|
|
949
|
-
while (
|
|
950
|
-
el &&
|
|
951
|
-
el !== this.countryList &&
|
|
952
|
-
!el.classList.contains("iti__country")
|
|
953
|
-
) {
|
|
954
|
-
el = el.parentNode;
|
|
955
|
-
}
|
|
956
|
-
// if we reached the countryList element, then return null
|
|
957
|
-
return el === this.countryList ? null : el;
|
|
958
|
-
}
|
|
959
|
-
|
|
960
912
|
// we only bind dropdown listeners when the dropdown is open
|
|
961
913
|
_bindDropdownListeners() {
|
|
962
914
|
// when mouse over a list item, just highlight that one
|
|
963
915
|
// we add the class "highlight", so if they hit "enter" we know which one to select
|
|
964
916
|
this._handleMouseoverCountryList = (e) => {
|
|
965
917
|
// handle event delegation, as we're listening for this event on the countryList
|
|
966
|
-
const listItem =
|
|
918
|
+
const listItem = e.target.closest(".iti__country");
|
|
967
919
|
if (listItem) {
|
|
968
920
|
this._highlightListItem(listItem, false);
|
|
969
921
|
}
|
|
@@ -975,7 +927,7 @@ class Iti {
|
|
|
975
927
|
|
|
976
928
|
// listen for country selection
|
|
977
929
|
this._handleClickCountryList = (e) => {
|
|
978
|
-
const listItem =
|
|
930
|
+
const listItem = e.target.closest(".iti__country");
|
|
979
931
|
if (listItem) {
|
|
980
932
|
this._selectListItem(listItem);
|
|
981
933
|
}
|
|
@@ -1080,7 +1032,8 @@ class Iti {
|
|
|
1080
1032
|
if (
|
|
1081
1033
|
isReset ||
|
|
1082
1034
|
nameLower.includes(query) ||
|
|
1083
|
-
fullDialCode.includes(query)
|
|
1035
|
+
fullDialCode.includes(query) ||
|
|
1036
|
+
c.iso2.includes(query)
|
|
1084
1037
|
) {
|
|
1085
1038
|
this.countryList.appendChild(c.node);
|
|
1086
1039
|
// highlight the first item
|
|
@@ -1159,7 +1112,7 @@ class Iti {
|
|
|
1159
1112
|
) {
|
|
1160
1113
|
const useNational =
|
|
1161
1114
|
this.options.nationalMode ||
|
|
1162
|
-
(number.charAt(0) !== "+" && !this.options.
|
|
1115
|
+
(number.charAt(0) !== "+" && !this.options.showSelectedDialCode);
|
|
1163
1116
|
const { NATIONAL, INTERNATIONAL } = intlTelInputUtils.numberFormat;
|
|
1164
1117
|
const format = useNational ? NATIONAL : INTERNATIONAL;
|
|
1165
1118
|
number = intlTelInputUtils.formatNumber(
|
|
@@ -1196,9 +1149,9 @@ class Iti {
|
|
|
1196
1149
|
number = `+${number}`;
|
|
1197
1150
|
}
|
|
1198
1151
|
|
|
1199
|
-
// if
|
|
1152
|
+
// if showSelectedDialCode enabled, then consider the selected dial code to be part of the number
|
|
1200
1153
|
if (
|
|
1201
|
-
this.options.
|
|
1154
|
+
this.options.showSelectedDialCode &&
|
|
1202
1155
|
selectedDialCode &&
|
|
1203
1156
|
number.charAt(0) !== "+"
|
|
1204
1157
|
) {
|
|
@@ -1300,7 +1253,7 @@ class Iti {
|
|
|
1300
1253
|
// select the given flag, update the placeholder, title, and the active list item
|
|
1301
1254
|
// Note: called from _setInitialState, _updateFlagFromNumber, _selectListItem, setCountry
|
|
1302
1255
|
_setFlag(countryCode) {
|
|
1303
|
-
const { allowDropdown,
|
|
1256
|
+
const { allowDropdown, showSelectedDialCode, showFlags } = this.options;
|
|
1304
1257
|
|
|
1305
1258
|
const prevCountry = this.selectedCountryData.iso2
|
|
1306
1259
|
? this.selectedCountryData
|
|
@@ -1322,9 +1275,9 @@ class Iti {
|
|
|
1322
1275
|
);
|
|
1323
1276
|
}
|
|
1324
1277
|
|
|
1325
|
-
this._setSelectedCountryFlagTitleAttribute(countryCode,
|
|
1278
|
+
this._setSelectedCountryFlagTitleAttribute(countryCode, showSelectedDialCode);
|
|
1326
1279
|
|
|
1327
|
-
if (
|
|
1280
|
+
if (showSelectedDialCode) {
|
|
1328
1281
|
const dialCode = this.selectedCountryData.dialCode
|
|
1329
1282
|
? `+${this.selectedCountryData.dialCode}`
|
|
1330
1283
|
: "";
|
|
@@ -1370,13 +1323,13 @@ class Iti {
|
|
|
1370
1323
|
return prevCountry.iso2 !== countryCode;
|
|
1371
1324
|
}
|
|
1372
1325
|
|
|
1373
|
-
_setSelectedCountryFlagTitleAttribute(countryCode,
|
|
1326
|
+
_setSelectedCountryFlagTitleAttribute(countryCode, showSelectedDialCode) {
|
|
1374
1327
|
if (!this.selectedFlag) {
|
|
1375
1328
|
return;
|
|
1376
1329
|
}
|
|
1377
1330
|
|
|
1378
1331
|
let title;
|
|
1379
|
-
if (countryCode && !
|
|
1332
|
+
if (countryCode && !showSelectedDialCode) {
|
|
1380
1333
|
title = `${this.selectedCountryData.name}: +${this.selectedCountryData.dialCode}`;
|
|
1381
1334
|
} else if (countryCode) {
|
|
1382
1335
|
// For screen reader output, we don't want to include the dial code in the reader output twice
|
|
@@ -1391,7 +1344,7 @@ class Iti {
|
|
|
1391
1344
|
|
|
1392
1345
|
// when the input is in a hidden container during initialisation, we must inject some markup
|
|
1393
1346
|
// into the end of the DOM to calculate the correct offsetWidth
|
|
1394
|
-
// NOTE: this is only used when
|
|
1347
|
+
// NOTE: this is only used when showSelectedDialCode is enabled, so flagsContainer and selectedFlag
|
|
1395
1348
|
// will definitely exist
|
|
1396
1349
|
_getHiddenSelectedFlagWidth() {
|
|
1397
1350
|
// to get the right styling to apply, all we need is a shallow clone of the container,
|
|
@@ -1451,10 +1404,6 @@ class Iti {
|
|
|
1451
1404
|
|
|
1452
1405
|
// focus the input
|
|
1453
1406
|
this.telInput.focus();
|
|
1454
|
-
// put cursor at end - this fix is required for FF and IE11 (with auto inserting dial code),
|
|
1455
|
-
// who try to put the cursor at the beginning the first time
|
|
1456
|
-
const len = this.telInput.value.length;
|
|
1457
|
-
this.telInput.setSelectionRange(len, len);
|
|
1458
1407
|
|
|
1459
1408
|
if (flagChanged) {
|
|
1460
1409
|
this._triggerCountryChange();
|
|
@@ -1502,7 +1451,7 @@ class Iti {
|
|
|
1502
1451
|
_scrollTo(element, middle) {
|
|
1503
1452
|
const container = this.dropdownContent;
|
|
1504
1453
|
// windowTop from https://stackoverflow.com/a/14384091/217866
|
|
1505
|
-
const windowTop =
|
|
1454
|
+
const windowTop = document.documentElement.scrollTop;
|
|
1506
1455
|
const containerHeight = container.offsetHeight;
|
|
1507
1456
|
const containerTop = container.getBoundingClientRect().top + windowTop;
|
|
1508
1457
|
const containerBottom = containerTop + containerHeight;
|
|
@@ -1595,7 +1544,7 @@ class Iti {
|
|
|
1595
1544
|
return dialCode;
|
|
1596
1545
|
}
|
|
1597
1546
|
|
|
1598
|
-
// get the input val, adding the dial code if
|
|
1547
|
+
// get the input val, adding the dial code if showSelectedDialCode is enabled
|
|
1599
1548
|
_getFullNumber() {
|
|
1600
1549
|
const val = this.telInput.value.trim();
|
|
1601
1550
|
const { dialCode } = this.selectedCountryData;
|
|
@@ -1603,12 +1552,12 @@ class Iti {
|
|
|
1603
1552
|
const numericVal = this._getNumeric(val);
|
|
1604
1553
|
|
|
1605
1554
|
if (
|
|
1606
|
-
this.options.
|
|
1555
|
+
this.options.showSelectedDialCode &&
|
|
1607
1556
|
val.charAt(0) !== "+" &&
|
|
1608
1557
|
dialCode &&
|
|
1609
1558
|
numericVal
|
|
1610
1559
|
) {
|
|
1611
|
-
// when using
|
|
1560
|
+
// when using showSelectedDialCode, it is visible so is effectively part of the typed number
|
|
1612
1561
|
prefix = `+${dialCode}`;
|
|
1613
1562
|
} else {
|
|
1614
1563
|
prefix = "";
|
|
@@ -1616,11 +1565,11 @@ class Iti {
|
|
|
1616
1565
|
return prefix + val;
|
|
1617
1566
|
}
|
|
1618
1567
|
|
|
1619
|
-
// remove the dial code if
|
|
1568
|
+
// remove the dial code if showSelectedDialCode is enabled
|
|
1620
1569
|
// also cap the length if the input has a maxlength attribute
|
|
1621
1570
|
_beforeSetNumber(fullNumber) {
|
|
1622
1571
|
let number = fullNumber;
|
|
1623
|
-
if (this.options.
|
|
1572
|
+
if (this.options.showSelectedDialCode) {
|
|
1624
1573
|
let dialCode = this._getDialCode(number);
|
|
1625
1574
|
// if there is a valid dial code
|
|
1626
1575
|
if (dialCode) {
|
|
@@ -1697,7 +1646,7 @@ class Iti {
|
|
|
1697
1646
|
this._handleFlagsContainerKeydown
|
|
1698
1647
|
);
|
|
1699
1648
|
// label click hack
|
|
1700
|
-
const label = this.
|
|
1649
|
+
const label = this.telInput.closest("label");
|
|
1701
1650
|
if (label) {
|
|
1702
1651
|
label.removeEventListener("click", this._handleLabelClick);
|
|
1703
1652
|
}
|
|
@@ -1781,19 +1730,19 @@ class Iti {
|
|
|
1781
1730
|
return -99;
|
|
1782
1731
|
}
|
|
1783
1732
|
|
|
1784
|
-
// validate the input val - assumes the global function
|
|
1733
|
+
// validate the input val - assumes the global function isPossibleNumber (from utilsScript)
|
|
1785
1734
|
isValidNumber() {
|
|
1786
1735
|
const val = this._getFullNumber().trim();
|
|
1787
1736
|
return window.intlTelInputUtils
|
|
1788
|
-
? intlTelInputUtils.
|
|
1737
|
+
? intlTelInputUtils.isPossibleNumber(val, this.selectedCountryData.iso2)
|
|
1789
1738
|
: null;
|
|
1790
1739
|
}
|
|
1791
1740
|
|
|
1792
|
-
//
|
|
1793
|
-
|
|
1741
|
+
// validate the input val (precise) - assumes the global function isValidNumber (from utilsScript)
|
|
1742
|
+
isValidNumberPrecise() {
|
|
1794
1743
|
const val = this._getFullNumber().trim();
|
|
1795
1744
|
return window.intlTelInputUtils
|
|
1796
|
-
? intlTelInputUtils.
|
|
1745
|
+
? intlTelInputUtils.isValidNumber(val, this.selectedCountryData.iso2)
|
|
1797
1746
|
: null;
|
|
1798
1747
|
}
|
|
1799
1748
|
|
|
@@ -2,7 +2,8 @@ var input,
|
|
|
2
2
|
iti,
|
|
3
3
|
totalCountries = 244,
|
|
4
4
|
totalDialCodes = 228,
|
|
5
|
-
defaultPreferredCountries =
|
|
5
|
+
defaultPreferredCountries = 0,
|
|
6
|
+
afghanistanDialCode = "+93";
|
|
6
7
|
|
|
7
8
|
var intlSetup = function(utilsScript) {
|
|
8
9
|
// by default put us in desktop mode
|
|
@@ -50,6 +51,16 @@ var getParentElement = function(i) {
|
|
|
50
51
|
return i.parent();
|
|
51
52
|
};
|
|
52
53
|
|
|
54
|
+
var getDropdownContent = function(i) {
|
|
55
|
+
i = i || input;
|
|
56
|
+
return i.parent().find(".iti__dropdown-content");
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
var getSearchInput = function(i) {
|
|
60
|
+
i = i || input;
|
|
61
|
+
return i.parent().find(".iti__search-input");
|
|
62
|
+
};
|
|
63
|
+
|
|
53
64
|
var getListElement = function(i) {
|
|
54
65
|
i = i || input;
|
|
55
66
|
return i.parent().find(".iti__country-list");
|
|
@@ -111,29 +122,31 @@ var selectInputChars = function(start, end) {
|
|
|
111
122
|
|
|
112
123
|
// use this for focus/blur (instead of using .focus() and .blur() directly, which cause problems in IE11)
|
|
113
124
|
var triggerInputEvent = function(type) {
|
|
114
|
-
var e = new
|
|
125
|
+
var e = new Event(type);
|
|
115
126
|
input[0].dispatchEvent(e);
|
|
116
127
|
}
|
|
117
128
|
|
|
118
129
|
var triggerKey = function(el, type, key) {
|
|
119
|
-
var e = new
|
|
120
|
-
e.key = key;
|
|
130
|
+
var e = new KeyboardEvent(type, { key: key });
|
|
121
131
|
el.dispatchEvent(e);
|
|
122
132
|
};
|
|
123
133
|
|
|
124
134
|
// trigger keydown, then keypress, then add the key, then keyup
|
|
125
|
-
var triggerKeyOnInput = function(key) {
|
|
126
|
-
|
|
127
|
-
triggerKey(
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
135
|
+
var triggerKeyOnInput = function(key, customInput) {
|
|
136
|
+
const inputEl = customInput || input;
|
|
137
|
+
triggerKey(inputEl[0], 'keydown', key);
|
|
138
|
+
triggerKey(inputEl[0], 'keypress', key);
|
|
139
|
+
var previousVal = inputEl.val();
|
|
140
|
+
inputEl.val(previousVal + key);
|
|
141
|
+
triggerKey(inputEl[0], 'keyup', key);
|
|
142
|
+
triggerKey(inputEl[0], 'input', key);
|
|
131
143
|
};
|
|
132
144
|
|
|
133
145
|
var triggerKeyOnBody = function(key) {
|
|
134
146
|
triggerKey(document, 'keydown', key);
|
|
135
147
|
triggerKey(document, 'keypress', key);
|
|
136
148
|
triggerKey(document, 'keyup', key);
|
|
149
|
+
triggerKey(document, 'input', key);
|
|
137
150
|
};
|
|
138
151
|
|
|
139
152
|
var triggerKeyOnFlagsContainerElement = function(key) {
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
describe("dropdown shortcuts: init plugin (with nationalMode=false, autoInsertDialCode=true) to test keyboard shortcuts", function() {
|
|
3
|
+
describe("dropdown shortcuts: init plugin (with countrySearch=false, nationalMode=false, autoInsertDialCode=true) to test keyboard shortcuts", function() {
|
|
4
4
|
|
|
5
5
|
beforeEach(function() {
|
|
6
6
|
intlSetup();
|
|
7
7
|
input = $("<input>").appendTo("body");
|
|
8
8
|
iti = window.intlTelInput(input[0], {
|
|
9
|
+
countrySearch: false,
|
|
9
10
|
nationalMode: false,
|
|
10
11
|
autoInsertDialCode: true,
|
|
11
12
|
});
|
|
@@ -138,7 +139,7 @@ describe("dropdown shortcuts: init plugin (with nationalMode=false, autoInsertDi
|
|
|
138
139
|
});
|
|
139
140
|
|
|
140
141
|
it("updates the dial code", function() {
|
|
141
|
-
expect(getInputVal()).toEqual("+
|
|
142
|
+
expect(getInputVal()).toEqual("+355");
|
|
142
143
|
});
|
|
143
144
|
|
|
144
145
|
});
|
|
@@ -25,14 +25,13 @@ describe("initial values:", function() {
|
|
|
25
25
|
|
|
26
26
|
it("has the right number of list items", function() {
|
|
27
27
|
expect(getListLength()).toEqual(totalCountries + defaultPreferredCountries);
|
|
28
|
-
expect(getPreferredCountriesLength()).toEqual(defaultPreferredCountries);
|
|
29
28
|
// only 1 active list item
|
|
30
29
|
expect(getActiveListItem().length).toEqual(1);
|
|
31
30
|
});
|
|
32
31
|
|
|
33
32
|
it("sets the state correctly: selected flag and active list item", function() {
|
|
34
|
-
expect(getSelectedFlagElement()).toHaveClass("
|
|
35
|
-
expect(getActiveListItem().attr("data-country-code")).toEqual("
|
|
33
|
+
expect(getSelectedFlagElement()).toHaveClass("iti__af");
|
|
34
|
+
expect(getActiveListItem().attr("data-country-code")).toEqual("af");
|
|
36
35
|
});
|
|
37
36
|
|
|
38
37
|
});
|
|
@@ -13,7 +13,7 @@ describe("getSelectedCountryData: init plugin to test public method getSelectedC
|
|
|
13
13
|
});
|
|
14
14
|
|
|
15
15
|
it("gets the right default country data", function() {
|
|
16
|
-
expect(iti.getSelectedCountryData().iso2).toEqual("
|
|
16
|
+
expect(iti.getSelectedCountryData().iso2).toEqual("af");
|
|
17
17
|
});
|
|
18
18
|
|
|
19
19
|
it("change country by number gets the right country data", function() {
|