@countriesdb/widget 0.1.25 → 0.1.27
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/dist/index.esm.js +89 -41
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +89 -41
- package/dist/index.js.map +1 -1
- package/dist/initialization.js +88 -41
- package/dist/types.d.ts +7 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -752,27 +752,47 @@
|
|
|
752
752
|
select.innerHTML += `<option value="${defaultValue}" disabled>Error: No country select present</option>`;
|
|
753
753
|
}
|
|
754
754
|
}
|
|
755
|
+
// Remove old event handlers if they exist (for re-initialization)
|
|
756
|
+
const oldHandlers = state.eventHandlers.get(select);
|
|
757
|
+
if (oldHandlers) {
|
|
758
|
+
if (oldHandlers.update) {
|
|
759
|
+
select.removeEventListener('change', oldHandlers.update);
|
|
760
|
+
}
|
|
761
|
+
if (oldHandlers.followRelated) {
|
|
762
|
+
select.removeEventListener('change', oldHandlers.followRelated);
|
|
763
|
+
}
|
|
764
|
+
if (oldHandlers.followUpward) {
|
|
765
|
+
select.removeEventListener('change', oldHandlers.followUpward);
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
// Create new event handlers
|
|
769
|
+
const handlers = {};
|
|
755
770
|
// Always dispatch an update event for user-initiated subdivision changes
|
|
756
|
-
|
|
771
|
+
handlers.update = (event) => {
|
|
757
772
|
if (isWidgetInitiatedEvent(event)) {
|
|
758
773
|
return;
|
|
759
774
|
}
|
|
760
775
|
dispatchUpdateEvent(select, { type: 'subdivision', reason: 'regular' });
|
|
761
|
-
}
|
|
776
|
+
};
|
|
777
|
+
select.addEventListener('change', handlers.update);
|
|
762
778
|
// --- follow_related (forward direction) ---
|
|
763
|
-
|
|
779
|
+
handlers.followRelated = async (event) => {
|
|
764
780
|
if (isWidgetInitiatedEvent(event)) {
|
|
765
781
|
return;
|
|
766
782
|
}
|
|
767
783
|
await handleFollowRelatedFromSubdivision(select, apiKey, backendUrl, state, config.followRelated, (s, key, code) => updateSubdivisionSelect(s, key, backendUrl, state, config, code));
|
|
768
|
-
}
|
|
784
|
+
};
|
|
785
|
+
select.addEventListener('change', handlers.followRelated);
|
|
769
786
|
// --- follow_upward (reverse direction) ---
|
|
770
|
-
|
|
787
|
+
handlers.followUpward = async (event) => {
|
|
771
788
|
if (isWidgetInitiatedEvent(event)) {
|
|
772
789
|
return;
|
|
773
790
|
}
|
|
774
791
|
await handleFollowUpwardFromSubdivision(select, apiKey, backendUrl, state, config.followUpward, (s, key, code) => updateSubdivisionSelect(s, key, backendUrl, state, config, code));
|
|
775
|
-
}
|
|
792
|
+
};
|
|
793
|
+
select.addEventListener('change', handlers.followUpward);
|
|
794
|
+
// Store handlers for future cleanup
|
|
795
|
+
state.eventHandlers.set(select, handlers);
|
|
776
796
|
}
|
|
777
797
|
}
|
|
778
798
|
/**
|
|
@@ -824,6 +844,11 @@
|
|
|
824
844
|
const dataDefaultValue = !isMultiple
|
|
825
845
|
? select.dataset.defaultValue
|
|
826
846
|
: undefined;
|
|
847
|
+
// Preserve user's current selection before clearing innerHTML
|
|
848
|
+
// This prevents preselected values from overwriting user selections
|
|
849
|
+
const currentValue = select.value;
|
|
850
|
+
const defaultValue = select.dataset.defaultValue || '';
|
|
851
|
+
const hasUserSelection = currentValue && currentValue !== defaultValue && currentValue.trim() !== '';
|
|
827
852
|
select.innerHTML = buildSubdivisionOptionsHTML(subdivisions, select, subdivisionsLanguage, config.showSubdivisionType, config.allowParentSelection, config.subdivisionNameFilter);
|
|
828
853
|
// Restore data attributes after setting innerHTML
|
|
829
854
|
if (!isMultiple) {
|
|
@@ -834,41 +859,53 @@
|
|
|
834
859
|
select.dataset.defaultValue = dataDefaultValue;
|
|
835
860
|
}
|
|
836
861
|
}
|
|
837
|
-
//
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
}
|
|
846
|
-
valueSetByWidget = true;
|
|
847
|
-
await triggerFollowLogic(select, apiKey, backendUrl, state, config.followRelated, config.followUpward, (s, key, code) => updateSubdivisionSelect(s, key, backendUrl, state, config, code), (countrySelect, key) => updateSubdivisions(countrySelect, key, backendUrl, state, config));
|
|
862
|
+
// Restore user's selection if it exists in the new options (user selection takes priority)
|
|
863
|
+
let userSelectionRestored = false;
|
|
864
|
+
if (hasUserSelection && !isMultiple) {
|
|
865
|
+
const optionExists = Array.from(select.options).some(opt => opt.value === currentValue);
|
|
866
|
+
if (optionExists) {
|
|
867
|
+
select.value = currentValue;
|
|
868
|
+
userSelectionRestored = true;
|
|
869
|
+
// Don't dispatch event here - user already selected it, no need to notify again
|
|
870
|
+
}
|
|
848
871
|
}
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
if (
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
872
|
+
// Manual preselection only if user hasn't selected anything
|
|
873
|
+
if (!userSelectionRestored) {
|
|
874
|
+
// Check if preselected value exists (applyPreselectedValue will read it from select element)
|
|
875
|
+
const hasPreselectedValue = (select.getAttribute('data-preselected') || select.dataset.preselected || select.dataset._widgetTempPreselect) !== undefined;
|
|
876
|
+
if (hasPreselectedValue) {
|
|
877
|
+
applyPreselectedValue(select, apiKey);
|
|
878
|
+
dispatchUpdateEvent(select, {
|
|
879
|
+
type: 'subdivision',
|
|
880
|
+
reason: 'preselected',
|
|
881
|
+
});
|
|
882
|
+
valueSetByWidget = true;
|
|
883
|
+
await triggerFollowLogic(select, apiKey, backendUrl, state, config.followRelated, config.followUpward, (s, key, code) => updateSubdivisionSelect(s, key, backendUrl, state, config, code), (countrySelect, key) => updateSubdivisions(countrySelect, key, backendUrl, state, config));
|
|
884
|
+
}
|
|
885
|
+
else {
|
|
886
|
+
// Try GeoIP preselect (only if user hasn't selected anything)
|
|
887
|
+
if (shouldUseGeoIP) {
|
|
888
|
+
const preselectedSubdivision = subdivisions.find((subdivision) => subdivision.preselected);
|
|
889
|
+
if (preselectedSubdivision) {
|
|
890
|
+
const isMultiple = select.hasAttribute('multiple');
|
|
891
|
+
if (isMultiple) {
|
|
892
|
+
// For multi-select, find and select the option
|
|
893
|
+
const option = Array.from(select.options).find((opt) => opt.value === preselectedSubdivision.code);
|
|
894
|
+
if (option) {
|
|
895
|
+
option.selected = true;
|
|
896
|
+
}
|
|
860
897
|
}
|
|
898
|
+
else {
|
|
899
|
+
// Single select: set value directly
|
|
900
|
+
select.value = preselectedSubdivision.code;
|
|
901
|
+
}
|
|
902
|
+
dispatchUpdateEvent(select, {
|
|
903
|
+
type: 'subdivision',
|
|
904
|
+
reason: 'geoip',
|
|
905
|
+
});
|
|
906
|
+
valueSetByWidget = true;
|
|
907
|
+
await triggerFollowLogic(select, apiKey, backendUrl, state, config.followRelated, config.followUpward, (s, key, code) => updateSubdivisionSelect(s, key, backendUrl, state, config, code), (countrySelect, key) => updateSubdivisions(countrySelect, key, backendUrl, state, config));
|
|
861
908
|
}
|
|
862
|
-
else {
|
|
863
|
-
// Single select: set value directly
|
|
864
|
-
select.value = preselectedSubdivision.code;
|
|
865
|
-
}
|
|
866
|
-
dispatchUpdateEvent(select, {
|
|
867
|
-
type: 'subdivision',
|
|
868
|
-
reason: 'geoip',
|
|
869
|
-
});
|
|
870
|
-
valueSetByWidget = true;
|
|
871
|
-
await triggerFollowLogic(select, apiKey, backendUrl, state, config.followRelated, config.followUpward, (s, key, code) => updateSubdivisionSelect(s, key, backendUrl, state, config, code), (countrySelect, key) => updateSubdivisions(countrySelect, key, backendUrl, state, config));
|
|
872
909
|
}
|
|
873
910
|
}
|
|
874
911
|
}
|
|
@@ -991,8 +1028,13 @@
|
|
|
991
1028
|
// Subdivisions will be loaded by event handler
|
|
992
1029
|
loadedInitialSubdivisions = true;
|
|
993
1030
|
}
|
|
994
|
-
//
|
|
995
|
-
|
|
1031
|
+
// Remove old event handlers if they exist (for re-initialization)
|
|
1032
|
+
const oldCountryHandlers = state.eventHandlers.get(select);
|
|
1033
|
+
if (oldCountryHandlers?.countryChange) {
|
|
1034
|
+
select.removeEventListener('change', oldCountryHandlers.countryChange);
|
|
1035
|
+
}
|
|
1036
|
+
// Create new country change handler
|
|
1037
|
+
const countryChangeHandler = async (event) => {
|
|
996
1038
|
if (isWidgetInitiatedEvent(event)) {
|
|
997
1039
|
return;
|
|
998
1040
|
}
|
|
@@ -1014,7 +1056,12 @@
|
|
|
1014
1056
|
if (config.followUpward && !select.multiple && picked.is_subdivision_of) {
|
|
1015
1057
|
await handleFollowUpwardFromCountry(select, apiKey, backendUrl, state, config.followUpward, (s, key, code) => updateSubdivisionSelect(s, key, backendUrl, state, subdivisionConfig, code));
|
|
1016
1058
|
}
|
|
1017
|
-
}
|
|
1059
|
+
};
|
|
1060
|
+
// Store and attach the handler
|
|
1061
|
+
const countryHandlers = state.eventHandlers.get(select) || {};
|
|
1062
|
+
countryHandlers.countryChange = countryChangeHandler;
|
|
1063
|
+
state.eventHandlers.set(select, countryHandlers);
|
|
1064
|
+
select.addEventListener('change', countryChangeHandler);
|
|
1018
1065
|
}
|
|
1019
1066
|
catch (error) {
|
|
1020
1067
|
console.error('Failed to fetch countries:', error);
|
|
@@ -1089,6 +1136,7 @@
|
|
|
1089
1136
|
subdivisionsMap: new WeakMap(),
|
|
1090
1137
|
subdivisionsLanguageMap: new WeakMap(),
|
|
1091
1138
|
isInitializing: new Set(),
|
|
1139
|
+
eventHandlers: new WeakMap(),
|
|
1092
1140
|
};
|
|
1093
1141
|
// Use empty string if publicKey is missing (will show error when API calls fail)
|
|
1094
1142
|
const apiKey = config.publicKey || '';
|