jam-cloud/web/app/assets/javascripts/selectLocation.js

302 lines
9.4 KiB
JavaScript

(function (context, $) {
"use strict";
context.JK = context.JK || {};
context.JK.SelectLocation = Class.extend({
init: function ($countries, $regions, $cities, app, useEasyDropdown) {
this.api = context.JK.Rest();
this.logger = context.JK.logger;
this.loadingCitiesData = false;
this.loadingRegionsData = false;
this.loadingCountriesData = false;
this.nilOptionStr = '<option value=""></option>';
this.nilOptionText = 'n/a';
this.countriesLoaded = false;
this.$countries = $countries;
this.$regions = $regions;
this.$cities = $cities;
this.$deferred = null;
this.useEasyDropdown = useEasyDropdown === undefined ? true : useEasyDropdown;
this.app = app;
$countries.on('change', function (evt) {
evt.stopPropagation();
this.handleCountryChanged();
return false;
}.bind(this));
if($regions) {
$regions.on('change', function (evt) {
evt.stopPropagation();
this.handleRegionChanged();
return false;
}.bind(this));
}
},
selectCountry: function (country) {
if(this.useEasyDropdown) {
this.$countries.easyDropDown('select', country, true)
}
else {
this.$countries.val(country)
}
},
ready: function() {
return this.$deferred;
},
load: function (country, region, city) {
this.country = country;
this.region = region;
this.city = city;
if (!country) {
// this case shouldn't happen because sign up makes you pick a location. This is just 'in case', so that the UI is more error-resilient
this.logger.debug("user has no specified country: " + country)
country = 'US';
}
// make the 3 slower requests, which only matter if the user wants to affect their ISP or location
this.loadingCountriesData = true;
this.$deferred = this.api.getCountries()
.done(function (countriesx) {
this.populateCountriesx(countriesx["countriesx"], country);
}.bind(this))
.fail(this.app.ajaxError)
.always(function () {
this.loadingCountriesData = false;
}.bind(this))
if (country && this.$regions) {
this.loadingRegionsData = true;
this.api.getRegions({ country: country })
.done(function (regions) {
this.populateRegions(regions["regions"], region);
}.bind(this))
.fail(this.regionListFailure.bind(this))
.always(function () {
this.loadingRegionsData = false;
}.bind(this))
if (region && this.$cities) {
this.loadingCitiesData = true;
this.api.getCities({ country: country, region: region })
.done(function (cities) {
this.populateCities(cities["cities"], this.city)
}.bind(this))
.fail(this.cityListFailure.bind(this))
.always(function () {
this.loadingCitiesData = false;
}.bind(this))
}
}
return this.$deferred;
},
handleCountryChanged: function () {
var selectedCountry = this.$countries.val()
if(!this.$regions) {
return;
}
var selectedRegion = this.$regions.val()
var cityElement = this.$cities
this.updateRegionList(selectedCountry, this.$regions);
this.updateCityList(selectedCountry, null, cityElement);
},
handleRegionChanged: function () {
var selectedCountry = this.$countries.val()
var selectedRegion = this.$regions.val()
var cityElement = this.$cities;
this.updateCityList(selectedCountry, selectedRegion, cityElement);
},
updateRegionList: function (selectedCountry, regionElement) {
// only update region
if (selectedCountry) {
// set city disabled while updating
regionElement.attr('disabled', true).easyDropDown('disable');
this.loadingRegionsData = true;
regionElement.children().remove()
regionElement.append($(this.nilOptionStr).text('loading...'))
this.api.getRegions({ country: selectedCountry })
.done(this.getRegionsDone.bind(this))
.error(function (err) {
regionElement.children().remove()
regionElement.append($(this.nilOptionStr).text(this.nilOptionText))
}.bind(this))
.always(function () {
console.log("regions load: this.loadingRegionsData; " + this.loadingRegionsData)
this.loadingRegionsData = false;
}.bind(this))
}
else {
regionElement.children().remove()
regionElement.append($(this.nilOptionStr).text(this.nilOptionText))
}
},
updateCityList: function (selectedCountry, selectedRegion, cityElement) {
// only update cities
if (selectedCountry && selectedRegion) {
// set city disabled while updating
cityElement.attr('disabled', true).easyDropDown('disable');
this.loadingCitiesData = true;
cityElement.children().remove()
cityElement.append($(this.nilOptionStr).text('loading...'))
this.api.getCities({ country: selectedCountry, region: selectedRegion })
.done(this.getCitiesDone.bind(this))
.error(function (err) {
cityElement.children().remove()
cityElement.append($(this.nilOptionStr).text(this.nilOptionText))
}.bind(this))
.always(function () {
this.loadingCitiesData = false;
}.bind(this))
}
else {
cityElement.children().remove();
cityElement.append($(this.nilOptionStr).text(this.nilOptionText));
if(this.useEasyDropdown) {
context.JK.dropdown(cityElement);
}
}
},
getCitiesDone: function (data) {
this.populateCities(data['cities'], this.city);
},
getRegionsDone: function (data) {
this.populateRegions(data['regions'], this.region);
this.updateCityList(this.$countries.val(), this.$regions.val(), this.$cities);
},
writeCountry: function (index, countryx) {
if (!countryx.countrycode) return;
var option = $(this.nilOptionStr);
option.text(countryx.countryname ? countryx.countryname : countryx.countrycode);
option.attr("value", countryx.countrycode);
if (countryx.countrycode == this.country) {
this.foundCountry = true;
}
this.$countries.append(option);
},
populateCountriesx: function (countriesx) {
this.countriesLoaded = true;
// countriesx has the format [{countrycode: "US", countryname: "United States"}, ...]
this.foundCountry = false;
this.$countries.children().remove();
var nilOption = $(this.nilOptionStr);
nilOption.text(this.nilOptionText);
this.$countries.append(nilOption);
$.each(countriesx, this.writeCountry.bind(this));
if (!this.foundCountry) {
this.logger.warn("user has no country in the database. user's country:" + this.country)
// in this case, the user has a country that is not in the database
// this can happen in a development/test scenario, but let's assume it can
// happen in production too.
var option = $(this.nilOptionStr);
option.text(this.country);
option.attr("value", this.country);
this.$countries.append(option);
}
this.$countries.val(this.country);
this.$countries.attr("disabled", null).easyDropDown('enable');
if(this.useEasyDropdown) {
context.JK.dropdown(this.$countries);
}
},
writeRegion: function (index, region) {
if (!region) return;
var option = $(this.nilOptionStr)
option.text(region['name'])
option.attr("value", region['region'])
this.$regions.append(option)
},
populateRegions: function (regions, userRegion) {
this.$regions.children().remove()
var nilOption = $(this.nilOptionStr);
nilOption.text(this.nilOptionText);
this.$regions.append(nilOption);
$.each(regions, this.writeRegion.bind(this))
this.$regions.val(userRegion)
this.$regions.attr("disabled", null).easyDropDown('enable');
if(this.useEasyDropdown) {
context.JK.dropdown(this.$regions);
}
},
writeCity: function (index, city) {
if (!city) return;
var option = $(this.nilOptionStr)
option.text(city)
option.attr("value", city)
this.$cities.append(option)
},
populateCities: function (cities, userCity) {
this.$cities.children().remove();
var nilOption = $(this.nilOptionStr);
nilOption.text(this.nilOptionText);
this.$cities.append(nilOption);
$.each(cities, this.writeCity.bind(this))
this.$cities.val(userCity)
this.$cities.attr("disabled", null).easyDropDown('enable');
if(this.useEasyDropdown) {
context.JK.dropdown(this.$cities);
}
},
regionListFailure: function (jqXHR, textStatus, errorThrown) {
if (jqXHR.status == 422) {
this.logger.debug("no regions found for country: " + this.country);
}
else {
this.app.ajaxError(arguments);
}
},
cityListFailure: function (jqXHR, textStatus, errorThrown) {
if (jqXHR.status == 422) {
this.logger.debug("no cities found for country/region: " + this.country + "/" + this.region);
}
else {
this.app.ajaxError(arguments);
}
}
});
})(window, jQuery);