intl-tel-input 19.0.1 → 19.1.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 +14 -9
- package/build/css/demo.css +1 -2
- package/build/css/intlTelInput.css +5 -1
- package/build/js/data.js +1 -1
- package/build/js/data.min.js +1 -1
- package/build/js/intlTelInput-jquery.js +59 -7
- package/build/js/intlTelInput-jquery.min.js +3 -3
- package/build/js/intlTelInput.js +59 -7
- package/build/js/intlTelInput.min.js +3 -3
- package/build/js/utils.js +52 -41
- package/composer.json +1 -1
- package/demo.html +3 -2
- package/grunt/replace.js +1 -1
- package/package.json +1 -1
- package/screenshots/vanilla-search.png +0 -0
- package/src/css/demo.scss +1 -2
- package/src/css/intlTelInput.scss +6 -1
- package/src/js/intlTelInput.js +64 -5
- package/src/js/utils.js +19 -0
- package/src/spec/helpers/helpers.js +1 -1
package/src/js/intlTelInput.js
CHANGED
|
@@ -34,6 +34,8 @@ const defaults = {
|
|
|
34
34
|
excludeCountries: [],
|
|
35
35
|
// fix the dropdown width to the input width (rather than being as wide as the longest country name)
|
|
36
36
|
fixDropdownWidth: true,
|
|
37
|
+
// format the number as the user types
|
|
38
|
+
formatAsYouType: true,
|
|
37
39
|
// format the input value during initialisation and on setNumber
|
|
38
40
|
formatOnDisplay: true,
|
|
39
41
|
// geoIp lookup function
|
|
@@ -756,23 +758,72 @@ class Iti {
|
|
|
756
758
|
|
|
757
759
|
// initialize any key listeners
|
|
758
760
|
_initKeyListeners() {
|
|
759
|
-
|
|
760
|
-
|
|
761
|
+
let userOverrideFormatting = false;
|
|
762
|
+
// update flag on input event
|
|
763
|
+
this._handleKeyEvent = (e) => {
|
|
761
764
|
if (this._updateFlagFromNumber(this.telInput.value)) {
|
|
762
765
|
this._triggerCountryChange();
|
|
763
766
|
}
|
|
767
|
+
|
|
768
|
+
// if user types their own formatting char (not a plus or a numeric), then set the override
|
|
769
|
+
if (e && e.data && /[^+0-9]/.test(e.data)) {
|
|
770
|
+
userOverrideFormatting = true;
|
|
771
|
+
}
|
|
772
|
+
// if user removes all formatting chars, then reset the override
|
|
773
|
+
else if (!/[^+0-9]/.test(this.telInput.value)) {
|
|
774
|
+
userOverrideFormatting = false;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
if (this.options.formatAsYouType && !userOverrideFormatting) {
|
|
778
|
+
// maintain caret position after reformatting
|
|
779
|
+
const currentCaretPos = this.telInput.selectionStart;
|
|
780
|
+
const valueBeforeCaret = this.telInput.value.substring(0, currentCaretPos);
|
|
781
|
+
const relevantCharsBeforeCaret = valueBeforeCaret.replace(/[^+0-9]/g, "").length;
|
|
782
|
+
const isDeleteForwards = e && e.inputType === "deleteContentForward";
|
|
783
|
+
const formattedValue = this.formatNumberAsYouType();
|
|
784
|
+
const newCaretPos = this._translateCursorPosition(relevantCharsBeforeCaret, formattedValue, currentCaretPos, isDeleteForwards);
|
|
785
|
+
this.telInput.value = formattedValue
|
|
786
|
+
this.telInput.setSelectionRange(newCaretPos, newCaretPos);
|
|
787
|
+
}
|
|
764
788
|
};
|
|
765
|
-
this.telInput.addEventListener("
|
|
789
|
+
this.telInput.addEventListener("input", this._handleKeyEvent);
|
|
766
790
|
|
|
767
791
|
// update flag on cut/paste events (now supported in all major browsers)
|
|
768
792
|
this._handleClipboardEvent = () => {
|
|
769
793
|
// hack because "paste" event is fired before input is updated
|
|
770
|
-
setTimeout(this.
|
|
794
|
+
setTimeout(this._handleKeyEvent);
|
|
771
795
|
};
|
|
772
796
|
this.telInput.addEventListener("cut", this._handleClipboardEvent);
|
|
773
797
|
this.telInput.addEventListener("paste", this._handleClipboardEvent);
|
|
774
798
|
}
|
|
775
799
|
|
|
800
|
+
// iterate through the formattedValue until hit the right number of relevant chars
|
|
801
|
+
_translateCursorPosition(relevantChars, formattedValue, prevCaretPos, isDeleteForwards) {
|
|
802
|
+
// if the first char is a formatting char, and they backspace delete it:
|
|
803
|
+
// cursor should stay at the start (pos 0), rather than stick to the first digit (pos 1)
|
|
804
|
+
if (prevCaretPos === 0 && !isDeleteForwards) {
|
|
805
|
+
return 0;
|
|
806
|
+
}
|
|
807
|
+
let count = 0;
|
|
808
|
+
for (let i = 0; i < formattedValue.length; i++) {
|
|
809
|
+
if (/[+0-9]/.test(formattedValue[i])) {
|
|
810
|
+
count++;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
// normal case: stop when you hit the right number of relevant chars
|
|
814
|
+
// (cursor will be just after the final relevant char)
|
|
815
|
+
if (count === relevantChars && !isDeleteForwards) {
|
|
816
|
+
return i + 1;
|
|
817
|
+
}
|
|
818
|
+
// spacial case: delete forwards (fn + delete on a mac):
|
|
819
|
+
// wait until hit one extra relevant char, and put the cursor just before it (after any formatting chars)
|
|
820
|
+
if (isDeleteForwards && count === relevantChars + 1) {
|
|
821
|
+
return i;
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
return formattedValue.length;
|
|
825
|
+
}
|
|
826
|
+
|
|
776
827
|
// adhere to the input's maxlength attr
|
|
777
828
|
_cap(number) {
|
|
778
829
|
const max = this.telInput.getAttribute("maxlength");
|
|
@@ -1666,7 +1717,7 @@ class Iti {
|
|
|
1666
1717
|
}
|
|
1667
1718
|
|
|
1668
1719
|
// unbind key events, and cut/paste events
|
|
1669
|
-
this.telInput.removeEventListener("
|
|
1720
|
+
this.telInput.removeEventListener("input", this._handleKeyEvent);
|
|
1670
1721
|
this.telInput.removeEventListener("cut", this._handleClipboardEvent);
|
|
1671
1722
|
this.telInput.removeEventListener("paste", this._handleClipboardEvent);
|
|
1672
1723
|
|
|
@@ -1746,6 +1797,14 @@ class Iti {
|
|
|
1746
1797
|
: null;
|
|
1747
1798
|
}
|
|
1748
1799
|
|
|
1800
|
+
// format the number as the user types
|
|
1801
|
+
formatNumberAsYouType() {
|
|
1802
|
+
const val = this._getFullNumber().trim();
|
|
1803
|
+
return window.intlTelInputUtils
|
|
1804
|
+
? intlTelInputUtils.formatNumberAsYouType(val, this.selectedCountryData.iso2)
|
|
1805
|
+
: val;
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1749
1808
|
// update the selected flag, and update the input val accordingly
|
|
1750
1809
|
setCountry(originalCountryCode) {
|
|
1751
1810
|
const countryCode = originalCountryCode.toLowerCase();
|
package/src/js/utils.js
CHANGED
|
@@ -3,6 +3,24 @@ goog.provide("i18n.phonenumbers.demo");
|
|
|
3
3
|
goog.require("i18n.phonenumbers.PhoneNumberFormat");
|
|
4
4
|
goog.require("i18n.phonenumbers.PhoneNumberUtil");
|
|
5
5
|
goog.require("i18n.phonenumbers.Error");
|
|
6
|
+
goog.require('i18n.phonenumbers.AsYouTypeFormatter');
|
|
7
|
+
|
|
8
|
+
// format the number as the user types
|
|
9
|
+
const formatNumberAsYouType = (number, countryCode) => {
|
|
10
|
+
try {
|
|
11
|
+
// have to clean it first, as AYTF stops formatting as soon as it hits any formatting char (even it's own)
|
|
12
|
+
// (it's designed to be fed one char at a time, as opposed to every char every time)
|
|
13
|
+
const clean = number.replace(/[^+0-9]/g, "");
|
|
14
|
+
const formatter = new i18n.phonenumbers.AsYouTypeFormatter(countryCode);
|
|
15
|
+
let result = "";
|
|
16
|
+
for (let i = 0; i < clean.length; i++) {
|
|
17
|
+
result = formatter.inputDigit(clean.charAt(i));
|
|
18
|
+
}
|
|
19
|
+
return result;
|
|
20
|
+
} catch (e) {
|
|
21
|
+
return number;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
6
24
|
|
|
7
25
|
// format the given number to the given format
|
|
8
26
|
const formatNumber = (number, countryCode, formatArg) => {
|
|
@@ -158,6 +176,7 @@ const validationError = {
|
|
|
158
176
|
|
|
159
177
|
// exports
|
|
160
178
|
goog.exportSymbol("intlTelInputUtils", {});
|
|
179
|
+
goog.exportSymbol("intlTelInputUtils.formatNumberAsYouType", formatNumberAsYouType);
|
|
161
180
|
goog.exportSymbol("intlTelInputUtils.formatNumber", formatNumber);
|
|
162
181
|
goog.exportSymbol("intlTelInputUtils.getExampleNumber", getExampleNumber);
|
|
163
182
|
goog.exportSymbol("intlTelInputUtils.getExtension", getExtension);
|