react-geoidentify-country-selector
Version:
Identifier geocoder for country selector on react
216 lines (207 loc) • 9.21 kB
JavaScript
/**
* Created by roman on 19.10.17.
*/
import React from 'react';
import PropTypes from 'prop-types';
import YaGeocoder from '../../functions/ya-geocoder';
import { COUNTRIES } from '../../constants/Countries';
import './styles/bootstrap.min.css';
import './styles/flags.css';
import './styles/CountrySelector.css';
class CountrySelector extends React.Component {
constructor(props) {
super(props);
this.hide = this.hide.bind(this);
this.show = this.show.bind(this);
let defaultCountry = {};
if (this.props.defaultCountry) {
defaultCountry = COUNTRIES.find(item => {
return item.countryName === this.props.defaultCountry
});
} else if (this.props.defaultISOALPHA2Code) {
defaultCountry = COUNTRIES.find(item => {
return item.ISOALPHA2Code === this.props.defaultISOALPHA2Code
});
} else if (this.props.defaultISOALPHA3Code) {
defaultCountry = COUNTRIES.find(item => {
return item.ISOALPHA3Code === this.props.defaultISOALPHA3Code
});
} else if (this.props.defaultISONumericalCode) {
defaultCountry = COUNTRIES.find(item => {
return item.ISONumericalCode === this.props.defaultISONumericalCode
});
}
this.state = {
defaultPropsCountry: defaultCountry,
currentCountry: Object.keys(defaultCountry).length ?
defaultCountry.countryName : 'United States of America',
ISOALPHA2Code: Object.keys(defaultCountry).length ?
defaultCountry.ISOALPHA2Code : 'US',
ISOALPHA3Code: Object.keys(defaultCountry).length ?
defaultCountry.ISOALPHA3Code : 'USA',
ISONumericalCode: Object.keys(defaultCountry).length ?
defaultCountry.ISONumericalCode : 840,
displayedCountries: COUNTRIES,
isListVisible: false,
isFirst: true
};
}
componentWillUpdate(nextProps, nextState) {
if (this.state.currentCountry !== nextState.currentCountry &&
this.state.ISOALPHA2Code !== nextState.ISOALPHA2Code &&
this.state.ISOALPHA3Code !== nextState.ISOALPHA3Code &&
this.state.ISONumericalCode !== nextState.ISONumericalCode) {
this.props.getSelectedCountry(
{
countryName: nextState.currentCountry,
ISOALPHA2Code: nextState.ISOALPHA2Code,
ISOALPHA3Code: nextState.ISOALPHA3Code,
ISONumericalCode: nextState.ISONumericalCode
}
);
}
}
componentDidMount() {
if (typeof window !== 'undefined') {
this.props.getSelectedCountry(
{
countryName: this.state.defaultPropsCountry.countryName,
ISOALPHA2Code: this.state.defaultPropsCountry.ISOALPHA2Code,
ISOALPHA3Code: this.state.defaultPropsCountry.ISOALPHA3Code,
ISONumericalCode: this.state.defaultPropsCountry.ISONumericalCode
}
);
const yaGeocoder = new YaGeocoder();
navigator.geolocation.getCurrentPosition((position) => {
if (position) {
yaGeocoder.resolve(`${position.coords.longitude},${position.coords.latitude}`, (err, collection) => {
if (err) throw err;
const currentCountry = COUNTRIES.find(item => {
return item.ISOALPHA2Code === collection[0].country_code
});
this.setState({
...this.state,
currentCountry: currentCountry.countryName,
ISOALPHA2Code: currentCountry.ISOALPHA2Code,
ISOALPHA3Code: currentCountry.ISOALPHA3Code,
ISONumericalCode: currentCountry.ISONumericalCode
});
this.props.getSelectedCountry(
{
countryName: currentCountry.countryName,
ISOALPHA2Code: currentCountry.ISOALPHA2Code,
ISOALPHA3Code: currentCountry.ISOALPHA3Code,
ISONumericalCode: currentCountry.ISONumericalCode
}
);
});
}
});
}
}
handleSelectCountry(countryName, ISOALPHA2Code, ISOALPHA3Code, ISONumericalCode) {
this.setState({
...this.state,
currentCountry: countryName,
ISOALPHA2Code,
ISOALPHA3Code,
ISONumericalCode,
});
}
handleChangeCountry(e) {
const query = e.target.value.toLowerCase().trim();
const displayedCountries = COUNTRIES.filter(function(item) {
return item.countryName.toLowerCase().search(query) >= 0;
});
this.setState({
displayedCountries
});
}
focusInput(component) {
if (component) {
component.focus();
}
}
show(e) {
this.setState({
...this.state,
isListVisible: true
});
if (typeof window !== 'undefined' && e.target.tagName.toUpperCase() !== 'INPUT') {
document.addEventListener("click", this.hide);
}
}
hide(e) {
if (typeof window !== 'undefined' && e.target.tagName.toUpperCase() !== 'INPUT') {
this.setState({
...this.state,
isListVisible: false
});
document.removeEventListener("click", this.hide);
}
}
render() {
return (
<div className="form-group">
<div className="dropdown">
<div className="btn dropdown-toggle c-select" onClick={this.show}>
<span>
<img
className={this.state.ISOALPHA2Code ?
`flag ${this.state.ISOALPHA2Code.toLowerCase()} fnone c-dropdown-flag` :
'c-dropdown-flag'}
/>{this.state.currentCountry}
</span>
</div>
<div
className="dropdown-menu c-dropdown-menu"
style={this.state.isListVisible ? {display: 'block'} : {display: 'none'}}
>
<input
className="c-dropdown-input"
type="text"
ref={component => this.focusInput(component)}
onInput={this.handleChangeCountry.bind(this)}
/>
<div className="c-dropdown-menu-overflow">
<ul className="c-dropdown-ul">
{
this.state.displayedCountries.map((item, index) => {
const flag = item.ISOALPHA2Code.toLowerCase();
return (
<li
tabIndex={index}
className="dropdown-item c-dropdown-item"
key={item.ISOALPHA2Code}
onClick={(countryName, ISOALPHA2Code, ISOALPHA3Code, ISONumericalCode) =>
this.handleSelectCountry(
item.countryName,
item.ISOALPHA2Code,
item.ISOALPHA3Code,
item.ISONumericalCode
)
}
>
<a data-option={`${item.ISOALPHA2Code}`}>
<img className={`flag ${flag} fnone c-dropdown-flag`} /> {item.countryName}
</a>
</li>
)
})
}
</ul>
</div>
</div>
</div>
</div>
)
}
}
CountrySelector.propTypes = {
defaultCountry: PropTypes.string,
defaultISOALPHA2Code: PropTypes.string,
defaultISOALPHA3Code: PropTypes.string,
defaultISONumericalCode: PropTypes.number,
getSelectedCountry: PropTypes.func
};
export default CountrySelector;