221 lines
6.9 KiB
JavaScript
221 lines
6.9 KiB
JavaScript
/**
|
|
* Dependent country → state → city dropdowns for registration forms.
|
|
*/
|
|
(function () {
|
|
'use strict';
|
|
|
|
var CITIES_URL =
|
|
(typeof window !== 'undefined' && window.REGISTER_LOCATION_CITIES_URL) ||
|
|
'/geo/cities';
|
|
|
|
var countriesData = null;
|
|
|
|
function isValidCountriesMap(data) {
|
|
return (
|
|
data &&
|
|
typeof data === 'object' &&
|
|
!Array.isArray(data) &&
|
|
Object.keys(data).length > 0
|
|
);
|
|
}
|
|
|
|
function loadCountriesData() {
|
|
if (isValidCountriesMap(countriesData)) {
|
|
return Promise.resolve(countriesData);
|
|
}
|
|
if (isValidCountriesMap(window.REGISTER_LOCATION_COUNTRIES)) {
|
|
countriesData = window.REGISTER_LOCATION_COUNTRIES;
|
|
return Promise.resolve(countriesData);
|
|
}
|
|
return fetch('/geo/countries', { credentials: 'same-origin' })
|
|
.then(function (res) {
|
|
if (!res.ok) {
|
|
throw new Error('Failed to load countries data');
|
|
}
|
|
var ct = res.headers.get('content-type') || '';
|
|
if (ct.indexOf('json') === -1) {
|
|
throw new Error('Countries data returned non-JSON response');
|
|
}
|
|
return res.json();
|
|
})
|
|
.then(function (data) {
|
|
if (!isValidCountriesMap(data)) {
|
|
throw new Error('Countries data is empty or invalid');
|
|
}
|
|
countriesData = data;
|
|
return data;
|
|
});
|
|
}
|
|
|
|
function loadCities(country, state) {
|
|
var url =
|
|
CITIES_URL +
|
|
'?country=' +
|
|
encodeURIComponent(country) +
|
|
'&state=' +
|
|
encodeURIComponent(state);
|
|
function fetchCitiesFrom(endpoint) {
|
|
return fetch(endpoint, { credentials: 'same-origin' }).then(function (res) {
|
|
if (!res.ok) {
|
|
throw new Error('Failed to load cities');
|
|
}
|
|
var ct = res.headers.get('content-type') || '';
|
|
if (ct.indexOf('json') === -1) {
|
|
throw new Error('Cities endpoint returned non-JSON response');
|
|
}
|
|
return res.json();
|
|
});
|
|
}
|
|
|
|
return fetchCitiesFrom(url).catch(function () {
|
|
if (url.indexOf('/api/geo/cities') === -1) {
|
|
return fetchCitiesFrom('/api/geo/cities' + url.substring(url.indexOf('?')));
|
|
}
|
|
throw new Error('Failed to load cities');
|
|
}).then(function (data) {
|
|
return Array.isArray(data) ? data : [];
|
|
});
|
|
}
|
|
|
|
function fillSelect(select, options, placeholder) {
|
|
select.innerHTML = '';
|
|
var empty = document.createElement('option');
|
|
empty.value = '';
|
|
empty.textContent = placeholder;
|
|
select.appendChild(empty);
|
|
options.forEach(function (opt) {
|
|
var el = document.createElement('option');
|
|
el.value = opt;
|
|
el.textContent = opt;
|
|
select.appendChild(el);
|
|
});
|
|
}
|
|
|
|
function setCityMode(selectEl, inputEl, cityFieldName, mode, cities) {
|
|
cities = cities || [];
|
|
if (mode === 'select' && cities.length > 0) {
|
|
selectEl.style.display = '';
|
|
inputEl.style.display = 'none';
|
|
inputEl.removeAttribute('name');
|
|
inputEl.disabled = true;
|
|
inputEl.required = false;
|
|
selectEl.setAttribute('name', cityFieldName);
|
|
selectEl.disabled = false;
|
|
selectEl.required = true;
|
|
fillSelect(selectEl, cities, '-- Select City --');
|
|
} else {
|
|
selectEl.style.display = 'none';
|
|
inputEl.style.display = '';
|
|
selectEl.removeAttribute('name');
|
|
selectEl.disabled = true;
|
|
selectEl.required = false;
|
|
selectEl.value = '';
|
|
inputEl.setAttribute('name', cityFieldName);
|
|
inputEl.disabled = false;
|
|
inputEl.required = true;
|
|
inputEl.placeholder =
|
|
mode === 'select'
|
|
? 'Enter city (no list available for this state)'
|
|
: 'Enter city';
|
|
if (mode !== 'select') {
|
|
inputEl.value = '';
|
|
}
|
|
}
|
|
}
|
|
|
|
function initRegisterLocationDropdowns() {
|
|
var wrapper = document.querySelector('.register-location-fields');
|
|
var countrySelect = document.getElementById('country');
|
|
var stateSelect = document.getElementById('state');
|
|
var citySelect = document.getElementById('city');
|
|
var cityInput = document.querySelector('.register-location-city-input');
|
|
|
|
if (!wrapper || !countrySelect || !stateSelect || !citySelect || !cityInput) {
|
|
return Promise.resolve();
|
|
}
|
|
|
|
var cityFieldName = wrapper.getAttribute('data-city-field') || 'city';
|
|
|
|
return loadCountriesData().then(function (data) {
|
|
var countries = Object.keys(data).sort(function (a, b) {
|
|
return a.localeCompare(b);
|
|
});
|
|
fillSelect(countrySelect, countries, '-- Select Country --');
|
|
|
|
var defaultCountry = wrapper.getAttribute('data-default-country') || 'India';
|
|
if (defaultCountry && data[defaultCountry]) {
|
|
countrySelect.value = defaultCountry;
|
|
fillSelect(stateSelect, data[defaultCountry], '-- Select State --');
|
|
stateSelect.disabled = false;
|
|
}
|
|
|
|
countrySelect.addEventListener('change', function () {
|
|
var country = countrySelect.value;
|
|
stateSelect.value = '';
|
|
citySelect.value = '';
|
|
cityInput.value = '';
|
|
setCityMode(citySelect, cityInput, cityFieldName, 'input');
|
|
citySelect.disabled = true;
|
|
cityInput.disabled = true;
|
|
|
|
if (!country || !data[country]) {
|
|
fillSelect(stateSelect, [], '-- Select State --');
|
|
stateSelect.disabled = true;
|
|
return;
|
|
}
|
|
|
|
fillSelect(stateSelect, data[country], '-- Select State --');
|
|
stateSelect.disabled = false;
|
|
});
|
|
|
|
stateSelect.addEventListener('change', function () {
|
|
var country = countrySelect.value;
|
|
var state = stateSelect.value;
|
|
citySelect.value = '';
|
|
cityInput.value = '';
|
|
|
|
if (!country || !state) {
|
|
setCityMode(citySelect, cityInput, cityFieldName, 'input');
|
|
citySelect.disabled = true;
|
|
cityInput.disabled = true;
|
|
return;
|
|
}
|
|
|
|
cityInput.disabled = true;
|
|
citySelect.disabled = true;
|
|
|
|
loadCities(country, state)
|
|
.then(function (cities) {
|
|
if (cities.length > 0) {
|
|
setCityMode(citySelect, cityInput, cityFieldName, 'select', cities);
|
|
} else {
|
|
setCityMode(citySelect, cityInput, cityFieldName, 'input');
|
|
cityInput.disabled = false;
|
|
}
|
|
})
|
|
.catch(function (err) {
|
|
console.warn('City list unavailable, using text input', err);
|
|
setCityMode(citySelect, cityInput, cityFieldName, 'input');
|
|
cityInput.disabled = false;
|
|
});
|
|
});
|
|
|
|
if (countrySelect.value && data[countrySelect.value]) {
|
|
stateSelect.dispatchEvent(new Event('change'));
|
|
}
|
|
});
|
|
}
|
|
|
|
function bootRegisterLocationDropdowns() {
|
|
initRegisterLocationDropdowns().catch(function (err) {
|
|
console.error('Register location dropdowns failed to initialize', err);
|
|
});
|
|
}
|
|
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', bootRegisterLocationDropdowns);
|
|
} else {
|
|
bootRegisterLocationDropdowns();
|
|
}
|
|
})();
|