@jacksonavila/phone-lib 2.0.5 → 2.0.7
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 +6 -6
- package/package.json +1 -1
- package/phone-lib.cdn.js +3 -3
- package/phone-lib.js +225 -62
package/README.md
CHANGED
|
@@ -61,7 +61,7 @@ You can use PhoneLib directly from CDN without npm / Puedes usar PhoneLib direct
|
|
|
61
61
|
<!DOCTYPE html>
|
|
62
62
|
<html>
|
|
63
63
|
<head>
|
|
64
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jacksonavila/phone-lib@2.0.
|
|
64
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jacksonavila/phone-lib@2.0.7/phone-lib.css">
|
|
65
65
|
</head>
|
|
66
66
|
<body>
|
|
67
67
|
<div id="phone-container"></div>
|
|
@@ -69,7 +69,7 @@ You can use PhoneLib directly from CDN without npm / Puedes usar PhoneLib direct
|
|
|
69
69
|
<script type="importmap">
|
|
70
70
|
{
|
|
71
71
|
"imports": {
|
|
72
|
-
"@jacksonavila/phone-lib": "https://cdn.jsdelivr.net/npm/@jacksonavila/phone-lib@2.0.
|
|
72
|
+
"@jacksonavila/phone-lib": "https://cdn.jsdelivr.net/npm/@jacksonavila/phone-lib@2.0.7/phone-lib.js",
|
|
73
73
|
"libphonenumber-js": "https://esm.sh/libphonenumber-js@1.11.0"
|
|
74
74
|
}
|
|
75
75
|
}
|
|
@@ -89,8 +89,8 @@ You can use PhoneLib directly from CDN without npm / Puedes usar PhoneLib direct
|
|
|
89
89
|
```
|
|
90
90
|
|
|
91
91
|
**CDN URLs / URLs de CDN:**
|
|
92
|
-
- **jsDelivr:** `https://cdn.jsdelivr.net/npm/@jacksonavila/phone-lib@2.0.
|
|
93
|
-
- **unpkg:** `https://unpkg.com/@jacksonavila/phone-lib@2.0.
|
|
92
|
+
- **jsDelivr:** `https://cdn.jsdelivr.net/npm/@jacksonavila/phone-lib@2.0.7/`
|
|
93
|
+
- **unpkg:** `https://unpkg.com/@jacksonavila/phone-lib@2.0.7/`
|
|
94
94
|
|
|
95
95
|
### Method 2: Script Tag (All Browsers) / Método 2: Script Tag (Todos los Navegadores)
|
|
96
96
|
|
|
@@ -98,12 +98,12 @@ You can use PhoneLib directly from CDN without npm / Puedes usar PhoneLib direct
|
|
|
98
98
|
<!DOCTYPE html>
|
|
99
99
|
<html>
|
|
100
100
|
<head>
|
|
101
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jacksonavila/phone-lib@2.0.
|
|
101
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jacksonavila/phone-lib@2.0.7/phone-lib.css">
|
|
102
102
|
</head>
|
|
103
103
|
<body>
|
|
104
104
|
<div id="phone-container"></div>
|
|
105
105
|
|
|
106
|
-
<script src="https://cdn.jsdelivr.net/npm/@jacksonavila/phone-lib@2.0.
|
|
106
|
+
<script src="https://cdn.jsdelivr.net/npm/@jacksonavila/phone-lib@2.0.7/phone-lib.cdn.js"></script>
|
|
107
107
|
|
|
108
108
|
<script>
|
|
109
109
|
let phoneLib = null;
|
package/package.json
CHANGED
package/phone-lib.cdn.js
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* Carga libphonenumber-js dinámicamente y expone PhoneLib globalmente
|
|
5
5
|
*
|
|
6
6
|
* Uso:
|
|
7
|
-
* <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jacksonavila/phone-lib@2.0.
|
|
8
|
-
* <script src="https://cdn.jsdelivr.net/npm/@jacksonavila/phone-lib@2.0.
|
|
7
|
+
* <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jacksonavila/phone-lib@2.0.7/phone-lib.css">
|
|
8
|
+
* <script src="https://cdn.jsdelivr.net/npm/@jacksonavila/phone-lib@2.0.7/phone-lib.cdn.js"></script>
|
|
9
9
|
* <script>
|
|
10
10
|
* document.addEventListener('phoneLibReady', () => {
|
|
11
11
|
* const phoneLib = new PhoneLib('#container', {...});
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
'use strict';
|
|
18
18
|
|
|
19
19
|
// Versión del paquete (actualizar cuando se publique nueva versión)
|
|
20
|
-
const PACKAGE_VERSION = '2.0.
|
|
20
|
+
const PACKAGE_VERSION = '2.0.7';
|
|
21
21
|
const PACKAGE_NAME = '@jacksonavila/phone-lib';
|
|
22
22
|
|
|
23
23
|
// URLs de CDN
|
package/phone-lib.js
CHANGED
|
@@ -406,14 +406,17 @@ class PhoneLib {
|
|
|
406
406
|
* Obtiene el HTML del icono de flecha
|
|
407
407
|
*/
|
|
408
408
|
getArrowIcon() {
|
|
409
|
-
// Si hay un icono personalizado, usarlo
|
|
410
|
-
if (this.options.arrowIcon) {
|
|
411
|
-
|
|
409
|
+
// Si hay un icono personalizado, usarlo (validar que sea string)
|
|
410
|
+
if (this.options.arrowIcon && typeof this.options.arrowIcon === 'string') {
|
|
411
|
+
// Sanitización básica: remover scripts potencialmente peligrosos
|
|
412
|
+
// Nota: En producción, considerar usar una librería de sanitización
|
|
413
|
+
const sanitized = this.options.arrowIcon.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
|
|
414
|
+
return sanitized;
|
|
412
415
|
}
|
|
413
416
|
|
|
414
417
|
// Chevron SVG por defecto (simple, apuntando hacia abajo - solo líneas, sin relleno)
|
|
415
418
|
// Forma de chevron: dos líneas que forman una V apuntando hacia abajo
|
|
416
|
-
// Usa dos
|
|
419
|
+
// Usa dos líneas separadas para asegurar que se vea como chevron, no triángulo
|
|
417
420
|
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
418
421
|
<line x1="3" y1="5" x2="6" y2="8"/>
|
|
419
422
|
<line x1="6" y1="8" x2="9" y2="5"/>
|
|
@@ -657,94 +660,183 @@ class PhoneLib {
|
|
|
657
660
|
* Adjunta los event listeners
|
|
658
661
|
*/
|
|
659
662
|
attachEventListeners() {
|
|
663
|
+
// Remover listeners anteriores si existen (para evitar duplicados)
|
|
664
|
+
if (this._boundHandlers) {
|
|
665
|
+
this.removeEventListeners();
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// Guardar referencias a handlers para poder removerlos después
|
|
669
|
+
this._boundHandlers = {
|
|
670
|
+
dropdownClick: (e) => {
|
|
671
|
+
if (this.isDisabled) return;
|
|
672
|
+
e.stopPropagation();
|
|
673
|
+
this.toggleDropdown();
|
|
674
|
+
},
|
|
675
|
+
documentClick: (e) => {
|
|
676
|
+
if (!this.container.contains(e.target)) {
|
|
677
|
+
this.closeDropdown();
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
};
|
|
681
|
+
|
|
660
682
|
// Toggle dropdown
|
|
661
|
-
this.dropdownButton
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
this.toggleDropdown();
|
|
665
|
-
});
|
|
683
|
+
if (this.dropdownButton) {
|
|
684
|
+
this.dropdownButton.addEventListener('click', this._boundHandlers.dropdownClick);
|
|
685
|
+
}
|
|
666
686
|
|
|
667
687
|
// Cerrar dropdown al hacer click fuera
|
|
668
|
-
document.addEventListener('click',
|
|
669
|
-
if (!this.container.contains(e.target)) {
|
|
670
|
-
this.closeDropdown();
|
|
671
|
-
}
|
|
672
|
-
});
|
|
688
|
+
document.addEventListener('click', this._boundHandlers.documentClick);
|
|
673
689
|
|
|
674
690
|
// Seleccionar país
|
|
675
691
|
const countryItems = this.container.querySelectorAll('.phone-lib-country-item');
|
|
692
|
+
this._countryItemHandlers = [];
|
|
676
693
|
countryItems.forEach(item => {
|
|
677
|
-
|
|
694
|
+
const handler = () => {
|
|
678
695
|
if (item.classList.contains('disabled')) {
|
|
679
696
|
return; // No permitir seleccionar países deshabilitados
|
|
680
697
|
}
|
|
681
698
|
const iso2 = item.dataset.iso2;
|
|
682
699
|
const dialCode = item.dataset.dialCode;
|
|
683
|
-
|
|
684
|
-
|
|
700
|
+
if (iso2 && dialCode) {
|
|
701
|
+
this.selectCountry(iso2, dialCode);
|
|
702
|
+
}
|
|
703
|
+
};
|
|
704
|
+
item.addEventListener('click', handler);
|
|
705
|
+
this._countryItemHandlers.push({ item, handler });
|
|
685
706
|
});
|
|
686
707
|
|
|
687
708
|
// Input de teléfono
|
|
688
|
-
this.phoneInput
|
|
689
|
-
|
|
690
|
-
|
|
709
|
+
if (this.phoneInput) {
|
|
710
|
+
this._boundHandlers.phoneInput = (e) => {
|
|
711
|
+
if (this.isDisabled || this.isReadonly) return;
|
|
691
712
|
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
this.validatePhone();
|
|
695
|
-
}
|
|
696
|
-
});
|
|
713
|
+
// Obtener el valor actual del input
|
|
714
|
+
const inputValue = e.target.value;
|
|
697
715
|
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
this.emitEvent('focus');
|
|
701
|
-
});
|
|
716
|
+
// Procesar el input
|
|
717
|
+
this.handlePhoneInput(inputValue);
|
|
702
718
|
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
719
|
+
// Validación en tiempo real si está habilitada
|
|
720
|
+
if (this.options.validateOnInput) {
|
|
721
|
+
this.validatePhone();
|
|
722
|
+
}
|
|
723
|
+
};
|
|
724
|
+
|
|
725
|
+
this._boundHandlers.phoneFocus = () => {
|
|
726
|
+
this.executeCallback('onFocus');
|
|
727
|
+
this.emitEvent('focus');
|
|
728
|
+
};
|
|
729
|
+
|
|
730
|
+
this._boundHandlers.phoneBlur = () => {
|
|
731
|
+
const isValid = this.validatePhone();
|
|
732
|
+
this.executeCallback('onBlur', this.phoneNumber, isValid);
|
|
733
|
+
this.emitEvent('blur', { phoneNumber: this.phoneNumber, isValid });
|
|
734
|
+
};
|
|
735
|
+
|
|
736
|
+
this.phoneInput.addEventListener('input', this._boundHandlers.phoneInput);
|
|
737
|
+
this.phoneInput.addEventListener('focus', this._boundHandlers.phoneFocus);
|
|
738
|
+
this.phoneInput.addEventListener('blur', this._boundHandlers.phoneBlur);
|
|
739
|
+
}
|
|
708
740
|
|
|
709
741
|
// Navegación por teclado en dropdown
|
|
710
742
|
this.setupKeyboardNavigation();
|
|
711
743
|
}
|
|
712
744
|
|
|
745
|
+
/**
|
|
746
|
+
* Remueve los event listeners
|
|
747
|
+
*/
|
|
748
|
+
removeEventListeners() {
|
|
749
|
+
// Remover listeners del botón
|
|
750
|
+
if (this.dropdownButton && this._boundHandlers?.dropdownClick) {
|
|
751
|
+
this.dropdownButton.removeEventListener('click', this._boundHandlers.dropdownClick);
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
// Remover listener del document
|
|
755
|
+
if (this._boundHandlers?.documentClick) {
|
|
756
|
+
document.removeEventListener('click', this._boundHandlers.documentClick);
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
// Remover listeners de items de países
|
|
760
|
+
if (this._countryItemHandlers) {
|
|
761
|
+
this._countryItemHandlers.forEach(({ item, handler }) => {
|
|
762
|
+
item.removeEventListener('click', handler);
|
|
763
|
+
});
|
|
764
|
+
this._countryItemHandlers = [];
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
// Remover listeners del input
|
|
768
|
+
if (this.phoneInput && this._boundHandlers) {
|
|
769
|
+
if (this._boundHandlers.phoneInput) {
|
|
770
|
+
this.phoneInput.removeEventListener('input', this._boundHandlers.phoneInput);
|
|
771
|
+
}
|
|
772
|
+
if (this._boundHandlers.phoneFocus) {
|
|
773
|
+
this.phoneInput.removeEventListener('focus', this._boundHandlers.phoneFocus);
|
|
774
|
+
}
|
|
775
|
+
if (this._boundHandlers.phoneBlur) {
|
|
776
|
+
this.phoneInput.removeEventListener('blur', this._boundHandlers.phoneBlur);
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
// Remover listeners de teclado
|
|
781
|
+
if (this._keyboardHandlers) {
|
|
782
|
+
if (this.dropdownButton && this._keyboardHandlers.buttonKeydown) {
|
|
783
|
+
this.dropdownButton.removeEventListener('keydown', this._keyboardHandlers.buttonKeydown);
|
|
784
|
+
}
|
|
785
|
+
if (this.dropdownMenu && this._keyboardHandlers.menuKeydown) {
|
|
786
|
+
this.dropdownMenu.removeEventListener('keydown', this._keyboardHandlers.menuKeydown);
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
|
|
713
791
|
/**
|
|
714
792
|
* Configura navegación por teclado
|
|
715
793
|
*/
|
|
716
794
|
setupKeyboardNavigation() {
|
|
717
795
|
if (!this.dropdownButton) return;
|
|
718
796
|
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
this.dropdownMenu.addEventListener('keydown', (e) => {
|
|
797
|
+
// Guardar handlers para poder removerlos después
|
|
798
|
+
this._keyboardHandlers = {
|
|
799
|
+
buttonKeydown: (e) => {
|
|
800
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
801
|
+
e.preventDefault();
|
|
802
|
+
this.toggleDropdown();
|
|
803
|
+
} else if (e.key === 'Escape') {
|
|
804
|
+
this.closeDropdown();
|
|
805
|
+
}
|
|
806
|
+
},
|
|
807
|
+
menuKeydown: (e) => {
|
|
731
808
|
const items = Array.from(this.container.querySelectorAll('.phone-lib-country-item:not([style*="display: none"])'));
|
|
809
|
+
if (items.length === 0) return;
|
|
810
|
+
|
|
732
811
|
const currentIndex = items.findIndex(item => item.classList.contains('selected'));
|
|
733
812
|
|
|
734
813
|
if (e.key === 'ArrowDown') {
|
|
735
814
|
e.preventDefault();
|
|
736
815
|
const nextIndex = (currentIndex + 1) % items.length;
|
|
737
|
-
items[nextIndex]
|
|
738
|
-
|
|
816
|
+
const nextItem = items[nextIndex];
|
|
817
|
+
if (nextItem && !nextItem.classList.contains('disabled')) {
|
|
818
|
+
nextItem.click();
|
|
819
|
+
nextItem.scrollIntoView({ block: 'nearest' });
|
|
820
|
+
}
|
|
739
821
|
} else if (e.key === 'ArrowUp') {
|
|
740
822
|
e.preventDefault();
|
|
741
823
|
const prevIndex = currentIndex <= 0 ? items.length - 1 : currentIndex - 1;
|
|
742
|
-
items[prevIndex]
|
|
743
|
-
|
|
824
|
+
const prevItem = items[prevIndex];
|
|
825
|
+
if (prevItem && !prevItem.classList.contains('disabled')) {
|
|
826
|
+
prevItem.click();
|
|
827
|
+
prevItem.scrollIntoView({ block: 'nearest' });
|
|
828
|
+
}
|
|
744
829
|
} else if (e.key === 'Escape') {
|
|
745
830
|
this.closeDropdown();
|
|
746
831
|
}
|
|
747
|
-
}
|
|
832
|
+
}
|
|
833
|
+
};
|
|
834
|
+
|
|
835
|
+
this.dropdownButton.addEventListener('keydown', this._keyboardHandlers.buttonKeydown);
|
|
836
|
+
|
|
837
|
+
// Navegación con flechas en el dropdown
|
|
838
|
+
if (this.dropdownMenu) {
|
|
839
|
+
this.dropdownMenu.addEventListener('keydown', this._keyboardHandlers.menuKeydown);
|
|
748
840
|
}
|
|
749
841
|
}
|
|
750
842
|
|
|
@@ -753,17 +845,34 @@ class PhoneLib {
|
|
|
753
845
|
*/
|
|
754
846
|
handlePhoneInput(value) {
|
|
755
847
|
const previousNumber = this.phoneNumber;
|
|
848
|
+
const previousCountry = this.selectedCountry;
|
|
756
849
|
this.phoneNumber = value;
|
|
757
850
|
|
|
758
851
|
// Detección automática de país si está habilitada
|
|
852
|
+
// IMPORTANTE: Hacer esto ANTES de formatear para que el formateo use el país correcto
|
|
759
853
|
if (this.options.autoDetectCountry && value) {
|
|
760
854
|
this.autoDetectCountry(value);
|
|
761
855
|
}
|
|
762
856
|
|
|
857
|
+
// Actualizar el número formateado (usará el país correcto si se detectó)
|
|
763
858
|
this.updatePhoneNumber();
|
|
764
859
|
|
|
765
860
|
// Ejecutar callbacks y eventos (validar sin actualizar visuals para obtener estado actual)
|
|
766
861
|
const isValid = this.phoneNumber ? this.validatePhone(false) : false;
|
|
862
|
+
|
|
863
|
+
// Emitir evento de cambio de país si cambió
|
|
864
|
+
if (previousCountry !== this.selectedCountry) {
|
|
865
|
+
const dialCode = this.getDialCode();
|
|
866
|
+
const countryData = this.countries.find(c => c.iso2 === this.selectedCountry);
|
|
867
|
+
this.executeCallback('onCountryChange', this.selectedCountry, dialCode, countryData?.name);
|
|
868
|
+
this.emitEvent('countryChange', {
|
|
869
|
+
country: this.selectedCountry,
|
|
870
|
+
dialCode,
|
|
871
|
+
countryName: countryData?.name,
|
|
872
|
+
previousCountry
|
|
873
|
+
});
|
|
874
|
+
}
|
|
875
|
+
|
|
767
876
|
this.executeCallback('onPhoneChange', this.phoneNumber, isValid, this.selectedCountry);
|
|
768
877
|
this.emitEvent('phoneChange', {
|
|
769
878
|
phoneNumber: this.phoneNumber,
|
|
@@ -801,7 +910,12 @@ class PhoneLib {
|
|
|
801
910
|
* Actualiza el número de teléfono y formatea
|
|
802
911
|
*/
|
|
803
912
|
updatePhoneNumber() {
|
|
913
|
+
if (!this.phoneInput) return;
|
|
914
|
+
|
|
804
915
|
if (!this.phoneNumber) {
|
|
916
|
+
if (this.phoneInput.value !== '') {
|
|
917
|
+
this.phoneInput.value = '';
|
|
918
|
+
}
|
|
805
919
|
if (this.hintElement) {
|
|
806
920
|
this.hintElement.textContent = '';
|
|
807
921
|
}
|
|
@@ -809,13 +923,48 @@ class PhoneLib {
|
|
|
809
923
|
}
|
|
810
924
|
|
|
811
925
|
try {
|
|
812
|
-
|
|
926
|
+
// Si el número empieza con +, intentar detectar el país para formatear correctamente
|
|
927
|
+
let countryForFormatting = this.selectedCountry;
|
|
928
|
+
if (this.phoneNumber && this.phoneNumber.startsWith('+')) {
|
|
929
|
+
try {
|
|
930
|
+
const parsed = parsePhoneNumber(this.phoneNumber);
|
|
931
|
+
if (parsed && parsed.country) {
|
|
932
|
+
// Usar el país detectado para formatear, si está disponible
|
|
933
|
+
const detectedCountry = parsed.country;
|
|
934
|
+
const countryAvailable = this.countries.find(c => c.iso2 === detectedCountry && !c.disabled);
|
|
935
|
+
if (countryAvailable) {
|
|
936
|
+
countryForFormatting = detectedCountry;
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
} catch (e) {
|
|
940
|
+
// Si no se puede detectar, usar el país seleccionado actual
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
const formatter = new AsYouType(countryForFormatting);
|
|
813
945
|
const formatted = formatter.input(this.phoneNumber);
|
|
814
946
|
|
|
947
|
+
// Solo actualizar si el valor formateado es diferente
|
|
815
948
|
if (formatted && formatted !== this.phoneInput.value) {
|
|
949
|
+
// Guardar la posición del cursor antes de actualizar
|
|
950
|
+
const cursorPosition = this.phoneInput.selectionStart;
|
|
951
|
+
const inputLength = this.phoneInput.value.length;
|
|
952
|
+
const wasAtEnd = cursorPosition === inputLength;
|
|
953
|
+
|
|
954
|
+
// Actualizar el valor
|
|
816
955
|
this.phoneInput.value = formatted;
|
|
817
|
-
|
|
818
|
-
|
|
956
|
+
|
|
957
|
+
// Restaurar la posición del cursor de manera inteligente
|
|
958
|
+
if (wasAtEnd) {
|
|
959
|
+
// Si estaba al final, mantenerlo al final
|
|
960
|
+
this.phoneInput.setSelectionRange(formatted.length, formatted.length);
|
|
961
|
+
} else {
|
|
962
|
+
// Intentar mantener la posición relativa
|
|
963
|
+
// Calcular la nueva posición basada en la diferencia de longitud
|
|
964
|
+
const lengthDiff = formatted.length - inputLength;
|
|
965
|
+
const newPosition = Math.max(0, Math.min(cursorPosition + lengthDiff, formatted.length));
|
|
966
|
+
this.phoneInput.setSelectionRange(newPosition, newPosition);
|
|
967
|
+
}
|
|
819
968
|
}
|
|
820
969
|
|
|
821
970
|
// Actualizar hint
|
|
@@ -913,12 +1062,24 @@ class PhoneLib {
|
|
|
913
1062
|
* Selecciona un país
|
|
914
1063
|
*/
|
|
915
1064
|
selectCountry(iso2, dialCode, silent = false) {
|
|
1065
|
+
// Validar que el país existe
|
|
1066
|
+
if (!iso2 || !dialCode) {
|
|
1067
|
+
console.warn('PhoneLib: selectCountry requiere iso2 y dialCode válidos');
|
|
1068
|
+
return;
|
|
1069
|
+
}
|
|
1070
|
+
|
|
916
1071
|
const previousCountry = this.selectedCountry;
|
|
917
1072
|
this.selectedCountry = iso2;
|
|
918
1073
|
|
|
919
1074
|
// Actualizar botón según el layout
|
|
920
1075
|
const countryData = this.countries.find(c => c.iso2 === iso2);
|
|
921
1076
|
|
|
1077
|
+
// Si el país no se encuentra, usar valores por defecto
|
|
1078
|
+
if (!countryData) {
|
|
1079
|
+
console.warn(`PhoneLib: País ${iso2} no encontrado en la lista`);
|
|
1080
|
+
return;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
922
1083
|
if (this.options.layout === 'separated') {
|
|
923
1084
|
// Layout separado: actualizar flag, nombre del país y código de marcación (si está visible)
|
|
924
1085
|
const flagElement = this.dropdownButton.querySelector('.phone-lib-flag');
|
|
@@ -955,9 +1116,11 @@ class PhoneLib {
|
|
|
955
1116
|
// Cerrar dropdown
|
|
956
1117
|
this.closeDropdown();
|
|
957
1118
|
|
|
958
|
-
// Actualizar placeholder y formato
|
|
959
|
-
this.phoneInput
|
|
960
|
-
|
|
1119
|
+
// Actualizar placeholder y formato (solo si el input existe)
|
|
1120
|
+
if (this.phoneInput) {
|
|
1121
|
+
this.phoneInput.placeholder = this.getPlaceholder();
|
|
1122
|
+
this.updatePhoneNumber();
|
|
1123
|
+
}
|
|
961
1124
|
|
|
962
1125
|
// Ejecutar callbacks y eventos solo si no es silencioso
|
|
963
1126
|
if (!silent) {
|
|
@@ -1249,11 +1412,8 @@ class PhoneLib {
|
|
|
1249
1412
|
* Destruye la instancia y limpia recursos
|
|
1250
1413
|
*/
|
|
1251
1414
|
destroy() {
|
|
1252
|
-
// Remover event listeners
|
|
1253
|
-
|
|
1254
|
-
const newInput = this.phoneInput.cloneNode(true);
|
|
1255
|
-
this.phoneInput.parentNode.replaceChild(newInput, this.phoneInput);
|
|
1256
|
-
}
|
|
1415
|
+
// Remover todos los event listeners
|
|
1416
|
+
this.removeEventListeners();
|
|
1257
1417
|
|
|
1258
1418
|
// Limpiar contenedor
|
|
1259
1419
|
if (this.container) {
|
|
@@ -1267,6 +1427,9 @@ class PhoneLib {
|
|
|
1267
1427
|
this.hintElement = null;
|
|
1268
1428
|
this.dialCodeInput = null;
|
|
1269
1429
|
this.countriesList = null;
|
|
1430
|
+
this._boundHandlers = null;
|
|
1431
|
+
this._countryItemHandlers = null;
|
|
1432
|
+
this._keyboardHandlers = null;
|
|
1270
1433
|
}
|
|
1271
1434
|
|
|
1272
1435
|
/**
|